import AppSettings from "@runtime/base/AppSettings";
import { ClientMessage } from "@runtime/generate/message/ClientMessage";
import DeviceComponent from "@runtime/module/Device/DeviceComponent";
import ModalComponent, { ModalOptions } from "@runtime/module/Modal/ModalComponent";
import RouterComponent from "@runtime/module/Router/RouterComponent";
import TimerComponent from "@runtime/module/Timer/TimerComponent";
import WebSocketComponent from "@runtime/module/WebSocket/WebSocketComponent";
import WebWindowComponent from "@runtime/module/WebWindow/WebWindowComponent";
import AnimatorComponent from "@runtime/UnityEngineBridge/AnimatorComponent";
import AssetLoaderComponent from "@runtime/UnityEngineBridge/AssetLoaderComponent";
import GameObjectComponent from "@runtime/UnityEngineBridge/GameObjectComponent";
import HighlighterComponent from "@runtime/UnityEngineBridge/HighlighterComponent";
import InteractableObjectComponent from "@runtime/UnityEngineBridge/InteractableObjectComponent";
import LabelComponent from "@runtime/UnityEngineBridge/LabelComponent";
import PostProcessLayerComponent from "@runtime/UnityEngineBridge/PostProcessLayerComponent";
import TooltipComponent from "@runtime/UnityEngineBridge/TooltipComponent";
import { computed, ComputedRef, reactive, ref, Ref, UnwrapNestedRefs, watch, WatchStopHandle } from "vue";
import BinocularCameraSettings from "./BinocularCameraSettings";
import OrbitCameraComponent from "./OrbitCameraComponent";
import RoomComponent from "./RoomComponent";

function ToMap<TKey, TValue>(sources: Array<TValue>, keySelector: (element: TValue) => TKey): Map<TKey, TValue> {
    const map = new Map<TKey, TValue>();
    for (const element of sources) {
        map.set(keySelector(element), element);
    }
    return map;
}

export const ModuleConfigs: ComputedRef<Array<{ Id: number, Name: string, Description: string, Icon: string }>> = computed(() => {
    const configs = [
        { Id: 1, Name: 'Introduction', Description: '系统简介', Icon: 'ic_menu_1' },
        { Id: 2, Name: 'Structure', Description: '结构认知', Icon: 'ic_menu_2' },
        { Id: 3, Name: 'Principle', Description: '工作原理', Icon: 'ic_menu_3' },
        { Id: 4, Name: 'Install', Description: '安装', Icon: 'ic_menu_4' },
        { Id: 5, Name: 'Calibration', Description: '标定', Icon: 'ic_menu_5' },
        { Id: 6, Name: 'Protocol', Description: '协议解读', Icon: 'ic_menu_6' },
        { Id: 7, Name: 'Usage', Description: '应用', Icon: 'ic_menu_7' },
    ];

    return configs;
});

class CoroutineLock implements Chaos.IDisposable {
    public Type: number = 0;
    public Key: number = 0;
    public Count: number = 0;

    private isCompleted: boolean = false;
    private task?: (value: void | PromiseLike<void>) => void;

    constructor(type: number, key: number, count: number) {
        this.Type = type;
        this.Key = key;
        this.Count = count;
    }

    async WaitAsync(): Promise<void> {
        if (this.isCompleted) {
            return;
        }

        return new Promise(resolve => this.task = resolve);
    }

    Dispose() {
        BinocularCameraComponent.Default.IsLoading.value = false;

        this.Type = 0;
        this.Key = 0;
        this.Count = 0;

        if (this.task != undefined) {
            this.task();
        }

        this.isCompleted = true;
    }
}

export class BinocularCameraConfig {
    public File: string = '';
}

export class ExamConfig {
    public Title: string;
    public Section: string;
    public System: string;
    public Type: string;
    public Weight: number;

    public Settings: BinocularCameraConfig | {} = {};

    constructor(title: string = '', section: string = '', system: string = '', type: string = '', weight: number = 0, contentTemplate: string = '', moduleOptions: Array<string> = [], systemOptions: Array<string> = [], typeOptions: Array<string> = []) {
        this.Title = title;
        this.Section = section;
        this.System = system;
        this.Type = type;
        this.Weight = weight;
    }
}

export class ExamContext {
    public Token: string = '';
    public Duration: number = 0;
    public ResultId: number = 0;
    public Mode: number = 0;
    public UserName: string = '';

    public Content?: string = '';

    public Configs: Array<ExamConfig> = [];


    public get HasBinocularCameraConfig(): boolean {
        return this.Configs.findIndex(config => config.System == '双目相机') > -1;
    }

    public get BinocularCamera(): BinocularCameraConfig {
        return this.Configs.find(config => config.System == '双目相机')!.Settings as BinocularCameraConfig;
    }

}

/**
 * 双目相机组件
 */
export default class BinocularCameraComponent {
    private static instance: BinocularCameraComponent = new BinocularCameraComponent();
    /**
     * 双目相机组件
     */
    public static get Default(): BinocularCameraComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.Module, this.OnModuleChangedAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public DeviceId: number = 0;

    public connect: Ref<string> = ref('');
    // public Status: ComputedRef<string> = computed(() => DeviceComponent.Default.Devices.get(this.DeviceId)?.Status ?? '');
    public Status: ComputedRef<string> = computed(() => DeviceComponent.Default.Devices.get(this.DeviceId)?.Status ?? this.connect.value);

    public IsLoading: Ref<boolean> = ref(false);
    public LoadingPercent: Ref<number> = ref(-1);
    public Context: UnwrapNestedRefs<ExamContext> = reactive(new ExamContext());
    public HasContext: ComputedRef<boolean> = computed(() => this.Context.Token != '');

    public Module: Ref<string> = ref('');

    private map: Map<number, Array<CoroutineLock>> = new Map();

    private hasInitialized: boolean = false;

    private watchStopHandles: Array<WatchStopHandle> = [];

    // public loadFile(name: any) {
    //   // name为文件所在位置
    //   let xhr = new XMLHttpRequest();
    //   const okStatus = document.location.protocol === "file:" ? 0 : 200;
    //   xhr.open("GET", name, false);
    //   xhr.overrideMimeType("text/html;charset=utf-8"); //默认为utf-8
    //   xhr.send(null);
    //   return xhr.status === okStatus ? xhr.responseText : null;
    // }
    // public aaa = this.loadFile("./project.config.txt");
    public async Awake(): Promise<void> {
        ModalComponent.Default.AddDynamicModules(import.meta.glob('/src/components/Apps/BinocularCamera/Exit.vue'));
        ModalComponent.Default.AddDynamicModules(import.meta.glob('/src/components/Apps/BinocularCamera/MessageBox.vue'));

        this.Module.value = 'Home';

        // 启动Unity
        const configuration = JSON.stringify({
            LocalAddress: AppSettings.Default.LocalAddress,
            ShortName: 'P10083',
            Type: 7,
        });
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.EmbeddedApplicationLaunchRequest('../EmbeddedApplication/Unity/Mix.Unity.exe', configuration));

        // 获取Unity版本状态
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.EmbeddedApplicationVersionRequest());
        // BinocularCameraSettings.Default.DeviceType,
        // BinocularCameraSettings.Default.DeviceIndex,
        // BinocularCameraSettings.Default.CanIndex,
        if (!this.hasInitialized) {
            await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceInitializationRequest(
                BinocularCameraSettings.Default.DeviceType,
                BinocularCameraSettings.Default.DeviceIndex,
                BinocularCameraSettings.Default.CanIndex,
            ));

            this.hasInitialized = true;
        }

        this.Module.value = 'Introduction';
    }

    public async Destroy(): Promise<void> {
    }

    /**
    * 模块发生变化时
    * @param value 模块
    */
    private async OnModuleChangedAsync(value: string): Promise<void> {
        // 切换至指定传感器路由
        const url = `/${AppSettings.Default.Type}/${value}`;
        await RouterComponent.Default.NavigateToAsync(url);
    }

    public async OnExitAsync(): Promise<void> {
        console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
        
        const volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
        console.log('################################',volume);
        
        const effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(volume);
        console.log('=================================================================',effect);
        
        const options = ModalOptions.Default()
            .WithPrefix('/src/components/Apps/BinocularCamera/')
            .WithType('Exit')
            .WithContent('是否确认退出软件?')
            .WithButtons(['确定', '取消']);
        const result = await ModalComponent.Default.PopupAsync(options);

        if (result == '确定') {
            WebSocketComponent.Default.PostMessage(new ClientMessage.ShutdownMessage());
        }

        await PostProcessLayerComponent.Default.RemoveEffectAsync(volume, effect);
        await PostProcessLayerComponent.Default.RemoveVolumeAsync(volume);
    }

    public async WaitAsync(type: number = 0, key: number = 0): Promise<CoroutineLock> {
        this.IsLoading.value = true;

        if (!this.map.has(key)) {
            this.map.set(key, []);
        }

        const locks = this.map.get(key)!;
        const lock = new CoroutineLock(type, key, locks.length);
        locks.add(lock);
        if (locks.length < 2) {
            return new Promise(resolve => resolve(lock));
        } else {
            const previous = locks[locks.length - 2];
            await previous.WaitAsync();
            return new Promise(resolve => resolve(lock));
        }
    }
}

/**
 * 简介
 */
export class IntroductionComponent {
    private static instance: IntroductionComponent = new IntroductionComponent();
    /**
     * 简介
     */
    public static get Default(): IntroductionComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public Title: string = '视觉传感器系统';

    public Description: string = `视觉传感器系统是模拟人的眼睛，利用左相机与右相机对于同一点观察的视差不同，通过三角形测距原理，再根据已知参数，对相机到该点的距离进行计算，从而获得障碍物的精准信息。同时双目相机还兼顾车道线、交通标识、障碍物类型的识别，为车道偏离预警、车道的保持、自适应巡航提供了信息支持。`;

    public Img: string = '/static/BinocularCamera/简介.png';

    private instanceId: number = 0;

    private watchStopHandles: Array<WatchStopHandle> = [];

    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetTransparentBackground();
        TooltipComponent.Default.Clear();

        if (this.instanceId == 0) {                                         
            this.instanceId = await AssetLoaderComponent.Default.LoadAsync('Assets/R00062/ICV/Res/Product/Introduction/双目相机系统/新石器双目相机系统.prefab');
        } else {
            await GameObjectComponent.Default.ShowAsync(this.instanceId);
        }

        await OrbitCameraComponent.Default.UpdateAsync([-0.9, 0.18, 0.03], 25, 26, 6, 0.1, 10);

        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        await GameObjectComponent.Default.HideAsync(this.instanceId);

        lock.Dispose();
    }
}

class StructureOptionConfig {
    Id: number;
    InstanceId: number;
    Type: string;
    Asset: string;
    /**
     * 动画状态
     */
    State: string;
    Description: string;
    ViewId: number;

    constructor(id: number, instanceId: number, type: string, asset: string, state: string, description: string, viewId: number) {
        this.Id = id;
        this.InstanceId = instanceId;
        this.Type = type;
        this.Asset = asset;
        this.State = state;
        this.Description = description;
        this.ViewId = viewId;
    }
}

class StructureConfig {
    Id: number;
    Name: string;
    Options: Array<number>;

    constructor(id: number, name: string, options: Array<number>) {
        this.Id = id;
        this.Name = name;
        this.Options = options;
    }
}

class TreeNode {
    public Id: number;
    public Parent: TreeNode | undefined;
    public Children: Array<TreeNode>;

    public Expand: boolean;

    public get HasChildren(): boolean {
        return this.Children.length != 0;
    }


    public get Indent(): number {
        return (this.Parent?.Indent ?? -1) + 1;
    }


    constructor(id: number, children: Array<TreeNode> = [], expand: boolean = false, parent: TreeNode | undefined = undefined) {
        this.Id = id;
        this.Parent = parent;
        this.Children = children;
        this.Expand = expand;

        for (const child of this.Children) {
            child.Parent = this;
        }
    }
}

/**
 * 结构认知
 */
export class StructureComponent {
    private static instance: StructureComponent = new StructureComponent();
    /**
     * 结构认知
     */
    public static get Default(): StructureComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.Id, this.OnIdChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.OptionId, this.OnOptionIdChangedAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public Node: UnwrapNestedRefs<TreeNode> = reactive(new TreeNode(1, [
        new TreeNode(2),
        new TreeNode(3),
        new TreeNode(4),
        new TreeNode(5),
        new TreeNode(6),
        new TreeNode(7),
        new TreeNode(8),
        new TreeNode(9),
        new TreeNode(10),
        new TreeNode(11),
        new TreeNode(12),
        new TreeNode(13),
        new TreeNode(14),
        new TreeNode(15),
        new TreeNode(16),
    ], true));

    /**
     * 结构配置
     */
    public Configs: UnwrapNestedRefs<Map<number, StructureConfig>> = reactive(ToMap<number, StructureConfig>([
        new StructureConfig(1, '双目相机系统', [1, 2]),
        new StructureConfig(2, '双目相机', [3, 4]),
        new StructureConfig(3, '信息显示屏', [5, 6]),
        new StructureConfig(4, '计算单元电源正极线束', [7]),
        new StructureConfig(5, '计算单元', [8]),
        new StructureConfig(6, '交换机至计算机网线', [9, 10]),
        new StructureConfig(7, '双目相机网线', [11, 12]),
        new StructureConfig(8, '交换机电源组合线束', [13]),
        new StructureConfig(9, '计算单元电源负极线束', [14]),
        new StructureConfig(10, '低压蓄电池', [15]),
        new StructureConfig(11, '保险丝盒', [16]),
        new StructureConfig(12, '保险丝盒电源正极线束', [17]),
        new StructureConfig(13, '交换机', [18]),
        new StructureConfig(14, '电源总开关', [19]),
        new StructureConfig(15, '电源总开关负极线束', [20]),
        new StructureConfig(16, '电源总开关负极线束接搭铁', [21]),
    ], element => element.Id));

    public Options: UnwrapNestedRefs<Map<number, StructureOptionConfig>> = reactive(ToMap<number, StructureOptionConfig>([
        new StructureOptionConfig(1, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/新石器双目相机系统组成.prefab', '', '', 4001),
        new StructureOptionConfig(2, 0, '组成', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/新石器双目相机系统组成.prefab', '', '', 4002),

        new StructureOptionConfig(3, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/双目相机.prefab', '', '', 4003),
        new StructureOptionConfig(4, 0, '组成', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/双目相机.prefab', 'Default', '', 4004),

        new StructureOptionConfig(5, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/信息显示屏.prefab', '', '', 4005),
        new StructureOptionConfig(6, 0, '组成', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/信息显示屏.prefab', '', '', 4006),

        new StructureOptionConfig(7, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/计算单元电源正极线束.prefab', '', '', 4015),

        new StructureOptionConfig(8, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/计算单元.prefab', '', '', 4007),

        new StructureOptionConfig(9, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/交换机至计算机网线.prefab', '', '', 4009),
        new StructureOptionConfig(10, 0, '组成', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/交换机至计算机网线.prefab', '', '', 4010),

        new StructureOptionConfig(11, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/双目相机网线.prefab', '', '', 4011),
        new StructureOptionConfig(12, 0, '组成', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/双目相机网线.prefab', '', '', 4012),

        new StructureOptionConfig(13, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/交换机电源组合线束.prefab', '', '', 4013),

        new StructureOptionConfig(14, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/计算单元电源负极线束.prefab', '', '', 4017),

        new StructureOptionConfig(15, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/低压蓄电池.prefab', '', '', 4020),
        
        new StructureOptionConfig(16, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/保险丝盒.prefab', '', '', 4034),
   
        new StructureOptionConfig(17, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/保险丝盒电源正级线束.prefab', '', '', 4036),

        new StructureOptionConfig(18, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/交换机.prefab', '', '', 4038),

        new StructureOptionConfig(19, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/电源总开关.prefab', '', '', 4040),

        new StructureOptionConfig(20, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/电源总开关负极线束.prefab', '', '', 4043),

        new StructureOptionConfig(21, 0, '结构', 'Assets/R00062/ICV/Res/Product/Structure/新石器双目相机系统/电源总开关负极线束接搭铁.prefab', '', '', 4044),
    ], element => element.Id));

    /**
     * 当前结构配置Id
     */
    public Id: Ref<number> = ref(1);

    /**
     * 当前结构配置选项Id
     */
    public OptionId: Ref<number> = ref(1);

    /**
     * 当前结构配置
     */
    public Config: ComputedRef<StructureConfig> = computed(() => this.Configs.get(this.Id.value)!);

    /**
     * 当前结构配置
     */
    public Option: ComputedRef<StructureOptionConfig> = computed(() => this.Options.get(this.OptionId.value)!);

    public FilterOptions: ComputedRef<Array<StructureOptionConfig>> = computed(() => Array.from(this.Options.values()).filter(config => this.Config.value.Options.includes(config.Id)));

    /**
     * 当前选项对应文本描述
     */
    public Description: ComputedRef<string> = computed(() => this.Options.get(this.OptionId.value)?.Description ?? 'adasdasdas');
    public DescriptionAudioAccessibility: Ref<boolean> = ref(true);

    private hasInitialized: boolean = false;
    private watchStopHandles: Array<WatchStopHandle> = [];

    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetTransparentBackground();
        TooltipComponent.Default.Clear();

        if (!this.hasInitialized) {
            await this.LoadAsync();
            this.hasInitialized = true;
        }

        await GameObjectComponent.Default.ShowAsync(this.Option.value.InstanceId);
        await OrbitCameraComponent.Default.ApplyConfigAsync(this.Option.value.ViewId);
        if (this.Option.value.Type == '组成') {
            // 加载标签
            await LabelComponent.Default.LoadAsync(this.Option.value.InstanceId);
        }

        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        LabelComponent.Default.Clear();
        await HighlighterComponent.Default.ClearAsync();

        await GameObjectComponent.Default.HideAsync(this.Option.value.InstanceId);

        lock.Dispose()
    }

    private FindNode(id: number): TreeNode | undefined {
        let node: TreeNode | undefined;

        function Find(id: number, input: TreeNode): void {
            if (input.Id == id) {
                node = input;
                return;
            }

            for (const child of input.Children) {
                Find(id, child);
            }
        }

        Find(id, this.Node);

        return node;
    }

    /**
     * 判断当年前节点是否有子节点
     * @param id 当前节点Id
     * @returns 是否有子节点
     */
    public HasChildren(id: number): boolean {
        return this.FindNode(id)?.HasChildren ?? false;
    }

    /**
     * 计算当前节点缩进级别
     * @param id 当前节点Id
     * @returns 当前节点缩进级别
     */
    public CalculateIndent(id: number): number {
        return this.FindNode(id)?.Indent ?? 0;
    }

    public CanShowNode(id: number): boolean {
        let node = this.FindNode(id)!;
        while (node.Parent != undefined) {
            if (!node.Parent.Expand) {
                return false;
            } else {
                node = node.Parent;
            }
        }
        return true;
    }

    public IsNodeExpand(id: number): boolean {
        return this.FindNode(id)?.Expand ?? false;
    }

    public SwitchNodeExpand(id: number): void {
        let node = this.FindNode(id)!;
        node.Expand = !node.Expand;
    }

    private async LoadAsync(): Promise<void> {
        this.Option.value.InstanceId = await AssetLoaderComponent.Default.LoadAsync(this.Option.value.Asset);
    }

    /**
     * Id发生变化时
     */
    private async OnIdChangedAsync(): Promise<void> {
        this.OptionId.value = this.Config.value.Options[0];
    }

    /**
     * 选项发生变化时
     * @param current 当前值
     * @param previous 过去值
     */
    private async OnOptionIdChangedAsync(current: number, previous: number): Promise<void> {
        BinocularCameraComponent.Default.IsLoading.value = true;

        if (import.meta.env.PROD) {
            await GameObjectComponent.Default.HideAsync(this.Options.get(previous)!.InstanceId);

            // 清空标签
            LabelComponent.Default.Clear();
            // 重置高亮
            await HighlighterComponent.Default.ClearAsync();

            if (this.Option.value.InstanceId == 0) {
                const volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
                const effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(volume);

                // 加载模型
                this.Option.value.InstanceId = await AssetLoaderComponent.Default.LoadAsync(this.Option.value.Asset);

                await PostProcessLayerComponent.Default.RemoveEffectAsync(volume, effect);
                await PostProcessLayerComponent.Default.RemoveVolumeAsync(volume);
            }

            // 显示当前选项模型
            await GameObjectComponent.Default.ShowAsync(this.Option.value.InstanceId);

            // 切换视角
            await OrbitCameraComponent.Default.ApplyConfigAsync(this.Option.value.ViewId);

            if (this.Option.value.State != '') {
                // 播放动画
                await AnimatorComponent.Default.PlayAsync(this.Option.value.InstanceId, this.Option.value.State, 1000);
            }

            if (this.Option.value.Type == '组成') {
                // 加载标签
                await LabelComponent.Default.LoadAsync(this.Option.value.InstanceId);
            }
        }

        BinocularCameraComponent.Default.IsLoading.value = false;
    }
}

class PrincipleConfig {
    Id: number;
    InstanceId: number;
    Name: string;
    Asset: string;
    /**
     * 动画状态
     */
    State: string;
    Description: string;
    ViewId: number;

    constructor(id: number, instanceId: number, name: string, asset: string, state: string, description: string, viewId: number) {
        this.Id = id;
        this.InstanceId = instanceId;
        this.Name = name;
        this.Asset = asset;
        this.State = state;
        this.Description = description;
        this.ViewId = viewId;
    }
}

/**
 * 工作原理
 */
export class PrincipleComponent {
    private static instance: PrincipleComponent = new PrincipleComponent();
    /**
     * 工作原理
     */
    public static get Default(): PrincipleComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.Id, this.OnIdChangedAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    /**
    * 当前原理配置
    */
    public Configs: UnwrapNestedRefs<Array<PrincipleConfig>> = reactive([
        new PrincipleConfig(
            1,
            0,
            '摄像机测距原理',
            'Assets/R00062/ICV/Res/Product/Principle/双目相机系统/摄像机测距原理.prefab',
            '',
            '单目相机通过与数据库图像库特征比对获得物品实际尺寸，然后通过计算图片中对应物体的像素大小来计算距离，当数据库匹配不上时，就无法计算距离，且精度较差。双目相机是模仿人眼的原理，将两个摄像头采集到的信息，相互补充，把看到的画面同步分析叠加处理，无需数据库比对类型，依靠两个平行布置的相机产生的视差，找到同一个物体所有的点，精确的测量三角距离，能够计算出摄像头与前方障碍物的距离，实现更高的识别精度和更远的探测范围。',
            4022),
    ]);

    /**
     * 当前原理配置Id
     */
    public Id: Ref<number> = ref(0);

    public Description: Ref<string> = ref('');
    public DescriptionAudioAccessibility: Ref<boolean> = ref(true);

    private watchStopHandles: Array<WatchStopHandle> = [];

    private instanceIds: Array<number> = [];

    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetTransparentBackground();
        TooltipComponent.Default.Clear();

        if (this.instanceIds.length == 0) {
            await this.LoadAsync(this.Configs.map(config => config.Asset));
            this.Id.value = this.Configs[0].Id;
        }

        const config = this.Configs.find(config => config.Id == this.Id.value)!;
        await GameObjectComponent.Default.ShowAsync(config.InstanceId);
        await OrbitCameraComponent.Default.ApplyConfigAsync(config.ViewId);

        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        await GameObjectComponent.Default.HideAsync(this.instanceIds);

        lock.Dispose();
    }

    private async LoadAsync(assets: Array<string>): Promise<void> {
        if (import.meta.env.DEV) {
            return;
        }

        const volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
        const effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(volume);

        this.instanceIds.clear();
        this.instanceIds.addRange(await AssetLoaderComponent.Default.LoadAllAsync(assets));

        await PostProcessLayerComponent.Default.RemoveEffectAsync(volume, effect);
        await PostProcessLayerComponent.Default.RemoveVolumeAsync(volume);

        for (let index = 0; index < this.instanceIds.length; ++index) {
            const instanceId = this.instanceIds[index];
            this.Configs[index].InstanceId = instanceId;
        }

        await GameObjectComponent.Default.HideAsync(this.instanceIds);
    }

    /**
     * 原理Id发生变化时
     * @param value 值
     */
    private async OnIdChangedAsync(value: number, previous: number): Promise<void> {
        // 更新结构数据
        const config = this.Configs.find(config => config.Id == value);
        const previousConfig = this.Configs.find(config => config.Id == previous);
        if (import.meta.env.PROD) {
            if (config != null) {
                if (previousConfig != null) {
                    await GameObjectComponent.Default.HideAsync(previousConfig.InstanceId);
                }

                await GameObjectComponent.Default.ShowAsync(config.InstanceId);
            } else {
                window.Logger.Error(`对应选项(Id:${value})不存在`);
            }
        }

        this.Description.value = config?.Description ?? '';
    }
}

class InstallStepConfig {
    Id: number;
    Name: string;
    Asset: string;

    constructor(id: number, name: string, asset: string) {
        this.Id = id;
        this.Name = name;
        this.Asset = asset;
    }
}

class InstallViewConfig {
    Id: number;
    Name: string;
    Icon: string;

    constructor(id: number, name: string, icon: string) {
        this.Id = id;
        this.Name = name;
        this.Icon = icon;
    }
}

/**
 * 安装组件
 */
export class InstallComponent {
    private static instance: InstallComponent = new InstallComponent();
    /**
     * 安装组件
     */
    public static get Default(): InstallComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.ViewId, this.OnViewChangedAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public StepDescriptions = ref<any>([
        {name:'1.安装低压蓄电池',type:false},
        {name:'2.安装保险丝盒',type:false},
        {name:'3.安装保险丝盒电源正级线束',type:false},
        {name:'4.安装电源总开关',type:false},
        {name:'5.安装电源总开关负极线束接搭铁',type:false},
        {name:'6.安装电源总开关负极线束',type:false},
        {name:'7.安装计算单元',type:false},
        {name:'8.安装计算单元电源负极线束',type:false},
        {name:'9.安装计算单元电源正极线束',type:false},
        {name:'10.安装交换机',type:false},
        {name:'11.安装交换机电源组合线束',type:false},
        {name:'12.安装交换机至计算机网线',type:false},
        {name:'13.安装双目相机',type:false},
        {name:'14.安装双目相机网线',type:false},
        {name:'15.安装信息显示屏',type:false},
    ])

    /**
     * 步骤提示
     */
    public StepTips: Array<InstallStepConfig> = [
        new InstallStepConfig(1, '步骤一', '安装说明001.png'),
        new InstallStepConfig(2, '步骤二', '安装说明002.png'),
        new InstallStepConfig(3, '步骤三', '安装说明003.png'),
        new InstallStepConfig(4, '步骤四', '安装说明004.png'),
    ];

    /**
     * 视角配置
     */
    public Views: Array<InstallViewConfig> = [
        new InstallViewConfig(4024, '目标', 'ic_mubiao'),
        new InstallViewConfig(4025, '零件桌', 'ic_lingjianzhuo'),
        new InstallViewConfig(4026, '零件桌', 'ic_lingjianzhuo'),
        new InstallViewConfig(4027, '零件桌', 'ic_lingjianzhuo'),
        new InstallViewConfig(4028, '车顶', 'ic_cheding'),
        new InstallViewConfig(4029, '车前', 'ic_cheqian'),
    ];

    public CanRecyclePart: ComputedRef<boolean> = computed(() => this.ViewId.value == 4025);

    public ViewId: Ref<number> = ref(0);

    public StepState: Ref<boolean> = ref(false);

    private watchStopHandles: Array<WatchStopHandle> = [];

    private instanceIds: Array<number> = [];

    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetTransparentBackground();
        TooltipComponent.Default.Clear();

        await RoomComponent.Default.ShowAsync();

        if (import.meta.env.PROD) {
            if (this.instanceIds.length == 0) {
                await this.LoadAsync([
                    'Assets/R00062/ICV/Res/Product/DisassemblyAndAssembly/零件桌/零件桌模块.prefab',
                    'Assets/R00062/ICV/Res/Product/DisassemblyAndAssembly/双目相机安装/[定位点]默认.prefab',
                    'Assets/R00062/ICV/Res/Product/DisassemblyAndAssembly/双目相机安装/[定位点]车顶.prefab',
                    'Assets/R00062/ICV/Res/Product/DisassemblyAndAssembly/双目相机安装/[定位点]车前.prefab',
                    'Assets/R00062/ICV/Res/Product/DisassemblyAndAssembly/双目相机安装/新石器双目相机安装.prefab'
                ]);
            } else {
                await GameObjectComponent.Default.ShowAsync(this.instanceIds);
            }
        }

        this.ViewId.value = this.Views[0].Id;
        await OrbitCameraComponent.Default.ApplyConfigAsync(this.ViewId.value);
        
        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        this.StepState.value = false;

        await GameObjectComponent.Default.HideAsync(this.instanceIds);

        await RoomComponent.Default.HideAsync();

        lock.Dispose();
    }

    private async LoadAsync(assets: Array<string>): Promise<void> {
        const volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
        const effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(volume);

        this.instanceIds.clear();
        this.instanceIds.addRange(await AssetLoaderComponent.Default.LoadAllAsync(assets));

        await PostProcessLayerComponent.Default.RemoveEffectAsync(volume, effect);
        await PostProcessLayerComponent.Default.RemoveVolumeAsync(volume);

        await InteractableObjectComponent.Default.LoadAsync(['BinocularCamera', 'BinocularCameraLocation']);
    }

    /**
     * 安装视角发生变化
     * @param viewId 值
     */
    private async OnViewChangedAsync(viewId: number): Promise<void> {
        if (import.meta.env.PROD) {
            OrbitCameraComponent.Default.ApplyConfigAsync(viewId);
        } else {
            window.Logger.Debug(`视角切换: ${viewId}`);
        }
    }

    public async RecycleAsync(id: number, instanceId: number): Promise<void> {
        InteractableObjectComponent.Default.Remove(id);
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.UncheckInteractableObjectRequest(id, instanceId));
        InteractableObjectComponent.Default.Choices.value.length -= 1     
    }
}

class CalibrationConfig {
    Id: number;
    Name: string;
    Asset: string;
    Options: Array<string>;
    ViewId: number;

    Descriptions: Map<string, string>;
    Records: Map<string, number>;

    /**
     * 物体实例Id
     */
    InstanceId: number;
    /**
     * 原点实例Id
     */
    Origin: number;
    /**
     * 是否显示原点
     */
    ShowOrigin: boolean;
    /**
     * 标定值
     */
    Values: Array<number>;

    constructor(id: number, name: string, asset: string, options: Array<string>, viewId: number, descriptions: Map<string, string>, records: Map<string, number>, instanceId: number = 0, origin: number = 0, showOrigin: boolean = false, values: Array<number> = []) {
        this.Id = id;
        this.Name = name;
        this.Asset = asset;
        this.Options = options;
        this.ViewId = viewId;

        this.Descriptions = descriptions;
        this.Records = records;

        this.InstanceId = instanceId;
        this.Origin = origin;
        this.ShowOrigin = showOrigin;
        this.Values = values;
    }
}

/**
 * 标定组件
 */
export class CalibrationComponent {
    private static instance: CalibrationComponent = new CalibrationComponent();
    /**
     * 标定组件
     */
    public static get Default(): CalibrationComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.Id, this.OnIdChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.ShowOrigin, this.OnOriginStateChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.ShowTips, this.OnPopupChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.ShowForms, this.OnPopupChangedAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public Configs: UnwrapNestedRefs<Map<number, CalibrationConfig>> = reactive(ToMap<number, CalibrationConfig>([
        new CalibrationConfig(1, '车辆坐标系标定',
            'Assets/R00062/ICV/Res/Product/Calibration/双目相机标定/新石器双目相机车辆坐标系标定.prefab',
            ['显示原点', '标定说明', '参数标定'],
            4031,
            new Map<string, string>([
                ["Car_W", "车辆左侧至右侧距离:"],
                ["Car_L", "车辆前侧至后侧距离:"],
                ["Radar_LX", "双目相机左相机至车辆左侧距离:"],
                // ["Radar_RX", "双目相机左相机至车辆右侧距离:"],
                ["Radar_Y", "双目相机左相机至车辆前侧距离:"],
                ["Radar_Z", "双目相机左相机至地面高度:"],
                ["Source_X", "车辆轮轴中心至车辆左侧距离:"],
                ["Source_Y", "车辆轮轴中心至车辆前(后)侧距离:"],
                ["Source_Z", "车辆轮轴中心至地面距离:"],
                // ["Bumper_Z", "车辆保险杠至地面距离:"],
            ]),
            new Map<string, number>([
                ["Car_W", 0],
                ["Car_L", 0],
                ["Radar_LX", 0],
                // ["Radar_RX", 0],
                ["Radar_Y", 0],
                ["Radar_Z", 0],
                ["Source_X", 0],
                ["Source_Y", 0],
                ["Source_Z", 0],
                // ["Bumper_Z", 0],
            ]),
        )
    ], element => element.Id));

    /**
     * 当前标定配置Id
     */
    public Id: Ref<number> = ref(1);

    public Config: ComputedRef<CalibrationConfig> = computed(() => this.Configs.get(this.Id.value)!);

    public Options: ComputedRef<Array<string>> = computed(() => this.Config.value.Options);

    /**
     * 姿态标定角度
     */
    private attibuteAngles: Array<number> = [0, 0, 0];

    public Tips = [
        '标定说明001.png',
        '标定说明002.png',
    ];

    /**
    * 显示原点
    */
    public ShowOrigin: Ref<boolean> = ref(false);
    /**
     * 显示标定说明
     */
    public ShowTips: Ref<boolean> = ref(false);
    /**
     * 显示参数标定
     */
    public ShowForms: Ref<boolean> = ref(false);

    // 标定X
    public pointX: Ref<any> = ref(0)
    // 标定Y
    public pointY: Ref<any> = ref(0)
    // 标定Z
    public pointZ: Ref<any> = ref(0)

    public AttitudeState: Ref<boolean> = ref(false);
    public AttitudePercent: Ref<number> = ref(0);

    private hasInitialized: boolean = false;

    private volume: number = 0;
    private effect: number = 0;

    private watchStopHandles: Array<WatchStopHandle> = [];

    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetTransparentBackground();
        TooltipComponent.Default.Clear();

        await RoomComponent.Default.ShowAsync();

        if (!this.hasInitialized) {
            await this.LoadAsync();
            this.hasInitialized = true;
        }

        await GameObjectComponent.Default.ShowAsync(this.Config.value.InstanceId);
        await OrbitCameraComponent.Default.ApplyConfigAsync(this.Config.value.ViewId);

        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        await GameObjectComponent.Default.HideAsync(this.Config.value.InstanceId);

        await RoomComponent.Default.HideAsync();

        // 隐藏坐标系尺寸标注
        TooltipComponent.Default.Clear();

        lock.Dispose();
    }

    /**
     * 切换原点显示状态
     * @param value 状态
     */
    private async OnOriginStateChangedAsync(value: boolean): Promise<void> {
        this.Config.value.ShowOrigin = value;

        if (value) {
            await GameObjectComponent.Default.ShowAsync(this.Config.value.Origin);
        } else {
            await GameObjectComponent.Default.HideAsync(this.Config.value.Origin);
        }
    }

    private async OnPopupChangedAsync(value: boolean): Promise<void> {
        if (value) {
            this.volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
            this.effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(this.volume);
        } else {
            await PostProcessLayerComponent.Default.RemoveEffectAsync(this.volume, this.effect);
            await PostProcessLayerComponent.Default.RemoveVolumeAsync(this.volume);
        }
    }

    private async LoadAsync(): Promise<void> {
        if (import.meta.env.DEV) {
            return;
        }

        const volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
        const effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(volume);

        const instanceIds = await AssetLoaderComponent.Default.LoadAllAsync(Array.from(this.Configs.values()).map(config => config.Asset));
        await GameObjectComponent.Default.HideAsync(instanceIds);
        const keys = Array.from(this.Configs.keys());
        for (let i = 0; i < keys.length; ++i) {
            this.Configs.get(keys[i])!.InstanceId = instanceIds[i];
        }

        // 初始化坐标系标定
        const gizmos: ClientMessage.BinocularCameraGizmosResponse = await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraGizmosRequest(this.Configs.get(1)!.InstanceId));
        this.Config.value.Origin = gizmos.Origin;
        this.Config.value.Values.addRange(gizmos.Values.map(value => Math.round(value * Math.pow(10, 2)) / Math.pow(10, 2)));

        await PostProcessLayerComponent.Default.RemoveEffectAsync(volume, effect);
        await PostProcessLayerComponent.Default.RemoveVolumeAsync(volume);
    }

    /**
     * 标定Id发生变化时
     * @param current 值
     */
    private async OnIdChangedAsync(current: number, previous: number): Promise<void> {
        if (import.meta.env.PROD) {
            TooltipComponent.Default.Clear();

            await GameObjectComponent.Default.HideAsync(this.Configs.get(previous)!.InstanceId);

            await GameObjectComponent.Default.ShowAsync(this.Config.value.InstanceId);

            await OrbitCameraComponent.Default.ApplyConfigAsync(this.Config.value.ViewId);
        }

        this.ShowOrigin.value = this.Config.value.ShowOrigin;
    }

    public async SubmitGizmosAsync(values: Array<number>): Promise<void> {
        const keys = Array.from(this.Configs.keys());
        const success = values.map(value => Math.round(value * Math.pow(10, 2)) / Math.pow(10, 2)).toString() == this.Configs.get(keys[0])!.Values.toString();
        const options = ModalOptions.Default()
            .WithPrefix('/src/components/Apps/BinocularCamera/')
            .WithType('MessageBox')
            .WithContent(success ? '标定成功' : '标定失败')
            .WithButtons(['确定']);
        await ModalComponent.Default.PopupAsync(options);
    }
}

/**
 * 协议定义
 */
export class ProtocolDefinitionConfig {
    Id: number;
    Type: number;
    Sign: string;
    StartIndex: number;
    Length: number;
    Resolution: number;
    Offset: number;
    Status: string;

    Value: string = '';
    Reference: string = '';

    constructor(id: number, type: number, sign: string, startIndex: number, length: number, resolution: number, offset: number, status: string) {
        this.Id = id;
        this.Type = type;
        this.Sign = sign;
        this.StartIndex = startIndex;
        this.Length = length;
        this.Resolution = resolution;
        this.Offset = offset;
        this.Status = status;
    }
}

/**
 * 协议图表定义
 */
export class ProtocolGraphConfig {
    Id: number;
    Type: number;
    Index: number;
    Name: string;
    Color: string;

    constructor(id: number, type: number, index: number, name: string, lt: string, lb: string, color: string) {
        this.Id = id;
        this.Type = type;
        this.Index = index;
        this.Name = name;
        this.Color = color;
    }
}

/**
 * 协议解读组件
 */
export class ProtocolComponent {
    private static instance: ProtocolComponent = new ProtocolComponent();
    /**
     * 协议解读组件
     */
    public static get Default(): ProtocolComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.Type, this.OnTypeChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.DataSource, this.OnDataSourceChanged.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public DefinitionConfigs: Array<ProtocolDefinitionConfig> = [
        // { "Id": 1001, "Type": 0x79F, "Sign": "OffSound", "StartIndex": 0, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "", "Value": "", "Reference": "" }, 
        { "Id": 1005, "Type": 0x79F, "Sign": "LeftLDW", "StartIndex": 7, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1004, "Type": 0x79F, "Sign": "RightLDW", "StartIndex": 6, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1003, "Type": 0x79F, "Sign": "LDWSentivity", "StartIndex": 4, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1002, "Type": 0x79F, "Sign": "Invalid", "StartIndex": 1, "Length": 3, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1001, "Type": 0x79F, "Sign": "OffSound", "StartIndex": 0, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1007, "Type": 0x79F, "Sign": "HMWGrade", "StartIndex": 14, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },        
        { "Id": 1006, "Type": 0x79F, "Sign": "HMW", "StartIndex": 8, "Length": 6, "Resolution": 0.1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1009, "Type": 0x79F, "Sign": "ErrorCode", "StartIndex": 17, "Length": 7, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1008, "Type": 0x79F, "Sign": "HMWEnable", "StartIndex": 16, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        // { "Id": 1010, "Type": 0x79F, "Sign": "SWVersion", "StartIndex": 24, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "", "Value": "", "Reference": "" },
        // { "Id": 1011, "Type": 0x79F, "Sign": "HWVersion", "StartIndex": 32, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "", "Value": "", "Reference": "" },
        { "Id": 1010, "Type": 0x79F, "Sign": "SWVersion", "StartIndex": 24, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1011, "Type": 0x79F, "Sign": "HWVersion", "StartIndex": 32, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1015, "Type": 0x79F, "Sign": "FcwLevel", "StartIndex": 46, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1014, "Type": 0x79F, "Sign": "AmbientLuminance", "StartIndex": 43, "Length": 3, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1013, "Type": 0x79F, "Sign": "FCWStatus", "StartIndex": 42, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 1012, "Type": 0x79F, "Sign": "VersionSegment", "StartIndex": 40, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        // { "Id": 1015, "Type": 0x79F, "Sign": "FcwLevel", "StartIndex": 46, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "", "Value": "", "Reference": "" },
        { "Id": 1016, "Type": 0x79F, "Sign": "CanProtocoIVersion", "StartIndex": 48, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 2001, "Type": 0x7A0, "Sign": "ObstacleNumber", "StartIndex": 0, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 2002, "Type": 0x7A0, "Sign": "TimeID", "StartIndex": 8, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        // { "Id": 2003, "Type": 0x7A0, "Sign": "YawAngle", "StartIndex": 16, "Length": 14, "Resolution": 0.0001, "Offset": -0.8191, "Status": "", "Value": "", "Reference": "" },
        // { "Id": 2004, "Type": 0x7A0, "Sign": "PitchAngle", "StartIndex": 32, "Length": 12, "Resolution": 0.0001, "Offset": -0.2047, "Status": "", "Value": "", "Reference": "" },
        // { "Id": 2005, "Type": 0x7A0, "Sign": "RotationAngle", "StartIndex": 44, "Length": 12, "Resolution": 0.0001, "Offset": -0.2047, "Status": "", "Value": "", "Reference": "" },
        { "Id": 2003, "Type": 0x7A0, "Sign": "YawAngle", "StartIndex": 16, "Length": 14, "Resolution": 0.0001, "Offset": -0.8191, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 2004, "Type": 0x7A0, "Sign": "PitchAngle", "StartIndex": 32, "Length": 12, "Resolution": 0.0001, "Offset": -0.2047, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 2005, "Type": 0x7A0, "Sign": "RotationAngle", "StartIndex": 44, "Length": 12, "Resolution": 0.0001, "Offset": -0.2047, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 2006, "Type": 0x7A0, "Sign": "HMWAlarm Threshold", "StartIndex": 56, "Length": 5, "Resolution": 0.1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 3001, "Type": 0x7A1, "Sign": "ObstacleID", "StartIndex": 0, "Length": 8, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 3002, "Type": 0x7A1, "Sign": "TrackNumber", "StartIndex": 8, "Length": 6, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 3003, "Type": 0x7A1, "Sign": "ObstacleWidth", "StartIndex": 16, "Length": 12, "Resolution": 0.01, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 3004, "Type": 0x7A1, "Sign": "ObstacleHeight", "StartIndex": 28, "Length": 12, "Resolution": 0.01, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 3005, "Type": 0x7A1, "Sign": "RelativeSpeedZ", "StartIndex": 40, "Length": 12, "Resolution": 0.0625, "Offset": -127.9375, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 3006, "Type": 0x7A1, "Sign": "DistanceY", "StartIndex": 52, "Length": 12, "Resolution": 0.01, "Offset": -20.47, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 4001, "Type": 0x7A2, "Sign": "DistanceX", "StartIndex": 0, "Length": 15, "Resolution": 0.01, "Offset": -163.83, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 4002, "Type": 0x7A2, "Sign": "DistanceZ", "StartIndex": 16, "Length": 15, "Resolution": 0.01, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 4003, "Type": 0x7A2, "Sign": "TTC", "StartIndex": 32, "Length": 6, "Resolution": 0.1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 4004, "Type": 0x7A2, "Sign": "HMW", "StartIndex": 38, "Length": 6, "Resolution": 0.1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 4005, "Type": 0x7A2, "Sign": "RelativeSpeedX", "StartIndex": 48, "Length": 10, "Resolution": 0.1, "Offset": -51.1, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 4006, "Type": 0x7A2, "Sign": "CIPV", "StartIndex": 58, "Length": 1, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 4007, "Type": 0x7A2, "Sign": "Obstacle Type", "StartIndex": 59, "Length": 4, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 5001, "Type": 0x7A3, "Sign": "LeftLaneStyle", "StartIndex": 0, "Length": 4, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 5002, "Type": 0x7A3, "Sign": "LeftLaneStatus", "StartIndex": 4, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 5003, "Type": 0x7A3, "Sign": "RightLaneStyle", "StartIndex": 8, "Length": 4, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 5004, "Type": 0x7A3, "Sign": "RightLaneStatus", "StartIndex": 12, "Length": 2, "Resolution": 1, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 5005, "Type": 0x7A3, "Sign": "CarDepth", "StartIndex": 16, "Length": 8, "Resolution": 0.01, "Offset": 0, "Status": "已支持输出", "Value": "", "Reference": "" },
        // { "Id": 5006, "Type": 0x7A3, "Sign": "SpeedOfRushLane", "StartIndex": 24, "Length": 10, "Resolution": 0.1, "Offset": -51.1, "Status": "内测中", "Value": "", "Reference": "" },
        { "Id": 5006, "Type": 0x7A3, "Sign": "SpeedOfRushLane", "StartIndex": 24, "Length": 10, "Resolution": 0.1, "Offset": -51.1, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 6001, "Type": 0x7A4, "Sign": "C0", "StartIndex": 0, "Length": 16, "Resolution": 0.001, "Offset": -32.767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 6002, "Type": 0x7A4, "Sign": "C1", "StartIndex": 16, "Length": 16, "Resolution": 0.0001, "Offset": -3.2767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 6003, "Type": 0x7A4, "Sign": "C2", "StartIndex": 32, "Length": 16, "Resolution": 0.000001, "Offset": -0.032767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 6004, "Type": 0x7A4, "Sign": "C3", "StartIndex": 48, "Length": 16, "Resolution": 0.000000001, "Offset": -0.000032767, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 7001, "Type": 0x7A5, "Sign": "C0", "StartIndex": 0, "Length": 16, "Resolution": 0.001, "Offset": -32.767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 7002, "Type": 0x7A5, "Sign": "C1", "StartIndex": 16, "Length": 16, "Resolution": 0.0001, "Offset": -3.2767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 7003, "Type": 0x7A5, "Sign": "C2", "StartIndex": 32, "Length": 16, "Resolution": 0.000001, "Offset": -0.032767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 7004, "Type": 0x7A5, "Sign": "C3", "StartIndex": 48, "Length": 16, "Resolution": 0.000000001, "Offset": -0.000032767, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 8001, "Type": 0x7A6, "Sign": "C0", "StartIndex": 0, "Length": 16, "Resolution": 0.001, "Offset": -32.767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 8002, "Type": 0x7A6, "Sign": "C1", "StartIndex": 16, "Length": 16, "Resolution": 0.0001, "Offset": -3.2767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 8003, "Type": 0x7A6, "Sign": "C2", "StartIndex": 32, "Length": 16, "Resolution": 0.000001, "Offset": -0.032767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 8004, "Type": 0x7A6, "Sign": "C3", "StartIndex": 48, "Length": 16, "Resolution": 0.000000001, "Offset": -0.000032767, "Status": "已支持输出", "Value": "", "Reference": "" },

        { "Id": 9001, "Type": 0x7A7, "Sign": "C0", "StartIndex": 0, "Length": 16, "Resolution": 0.001, "Offset": -32.767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 9002, "Type": 0x7A7, "Sign": "C1", "StartIndex": 16, "Length": 16, "Resolution": 0.0001, "Offset": -3.2767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 9003, "Type": 0x7A7, "Sign": "C2", "StartIndex": 32, "Length": 16, "Resolution": 0.000001, "Offset": -0.032767, "Status": "已支持输出", "Value": "", "Reference": "" },
        { "Id": 9004, "Type": 0x7A7, "Sign": "C3", "StartIndex": 48, "Length": 16, "Resolution": 0.000000001, "Offset": -0.000032767, "Status": "已支持输出", "Value": "", "Reference": "" },
    ];

    public GraphConfigs: Array<ProtocolGraphConfig> = [
        { "Id": 1001, "Type": 0x79F, "Index": 7, "Name": "LeftLDW", "Color": "#548235" },
        { "Id": 1002, "Type": 0x79F, "Index": 6, "Name": "RightLDW", "Color": "#ff66cc" },
        { "Id": 1003, "Type": 0x79F, "Index": 5, "Name": "LDWSentivity", "Color": "#c6e0b4" },
        { "Id": 1004, "Type": 0x79F, "Index": 4, "Name": "", "Color": "#c6e0b4" },
        { "Id": 1005, "Type": 0x79F, "Index": 3, "Name": "Invalid", "Color": "#f8cbad" },
        { "Id": 1006, "Type": 0x79F, "Index": 2, "Name": "", "Color": "#f8cbad" },
        { "Id": 1007, "Type": 0x79F, "Index": 1, "Name": "", "Color": "#f8cbad" },
        { "Id": 1008, "Type": 0x79F, "Index": 0, "Name": "OffSound", "Color": "#2f75b5" },
        { "Id": 1009, "Type": 0x79F, "Index": 15, "Name": "HMWGrade", "Color": "#ffc000" },
        { "Id": 1010, "Type": 0x79F, "Index": 14, "Name": "", "Color": "#ffc000" },
        { "Id": 1011, "Type": 0x79F, "Index": 13, "Name": "HMW", "Color": "#92d050" },
        { "Id": 1012, "Type": 0x79F, "Index": 12, "Name": "", "Color": "#92d050" },
        { "Id": 1013, "Type": 0x79F, "Index": 11, "Name": "", "Color": "#92d050" },
        { "Id": 1014, "Type": 0x79F, "Index": 10, "Name": "", "Color": "#92d050" },
        { "Id": 1015, "Type": 0x79F, "Index": 9, "Name": "", "Color": "#92d050" },
        { "Id": 1016, "Type": 0x79F, "Index": 8, "Name": "", "Color": "#92d050" },
        { "Id": 1017, "Type": 0x79F, "Index": 23, "Name": "ErrorCode", "Color": "#ed7d31" },
        { "Id": 1018, "Type": 0x79F, "Index": 22, "Name": "", "Color": "#ed7d31" },
        { "Id": 1019, "Type": 0x79F, "Index": 21, "Name": "", "Color": "#ed7d31" },
        { "Id": 1020, "Type": 0x79F, "Index": 20, "Name": "", "Color": "#ed7d31" },
        { "Id": 1021, "Type": 0x79F, "Index": 19, "Name": "", "Color": "#ed7d31" },
        { "Id": 1022, "Type": 0x79F, "Index": 18, "Name": "", "Color": "#ed7d31" },
        { "Id": 1023, "Type": 0x79F, "Index": 17, "Name": "", "Color": "#ed7d31" },
        { "Id": 1024, "Type": 0x79F, "Index": 16, "Name": "HMWEnable", "Color": "#7030a0" },
        { "Id": 1025, "Type": 0x79F, "Index": 31, "Name": "SWVersion", "Color": "#00b0f0" },
        { "Id": 1026, "Type": 0x79F, "Index": 30, "Name": "", "Color": "#00b0f0" },
        { "Id": 1027, "Type": 0x79F, "Index": 29, "Name": "", "Color": "#00b0f0" },
        { "Id": 1028, "Type": 0x79F, "Index": 28, "Name": "", "Color": "#00b0f0" },
        { "Id": 1029, "Type": 0x79F, "Index": 27, "Name": "", "Color": "#00b0f0" },
        { "Id": 1030, "Type": 0x79F, "Index": 26, "Name": "", "Color": "#00b0f0" },
        { "Id": 1031, "Type": 0x79F, "Index": 25, "Name": "", "Color": "#00b0f0" },
        { "Id": 1032, "Type": 0x79F, "Index": 24, "Name": "", "Color": "#00b0f0" },
        { "Id": 1033, "Type": 0x79F, "Index": 39, "Name": "HWVersion", "Color": "#ffd966" },
        { "Id": 1034, "Type": 0x79F, "Index": 38, "Name": "", "Color": "#ffd966" },
        { "Id": 1035, "Type": 0x79F, "Index": 37, "Name": "", "Color": "#ffd966" },
        { "Id": 1036, "Type": 0x79F, "Index": 36, "Name": "", "Color": "#ffd966" },
        { "Id": 1037, "Type": 0x79F, "Index": 35, "Name": "", "Color": "#ffd966" },
        { "Id": 1038, "Type": 0x79F, "Index": 34, "Name": "", "Color": "#ffd966" },
        { "Id": 1039, "Type": 0x79F, "Index": 33, "Name": "", "Color": "#ffd966" },
        { "Id": 1040, "Type": 0x79F, "Index": 32, "Name": "", "Color": "#ffd966" },
        { "Id": 1041, "Type": 0x79F, "Index": 47, "Name": "FcwLevel", "Color": "#2f75b5" },
        { "Id": 1042, "Type": 0x79F, "Index": 46, "Name": "", "Color": "#2f75b5" },
        { "Id": 1043, "Type": 0x79F, "Index": 45, "Name": "AmbientLuminance", "Color": "#a9d08e" },
        { "Id": 1044, "Type": 0x79F, "Index": 44, "Name": "", "Color": "#a9d08e" },
        { "Id": 1045, "Type": 0x79F, "Index": 43, "Name": "", "Color": "#a9d08e" },
        { "Id": 1046, "Type": 0x79F, "Index": 42, "Name": "FCWStatus", "Color": "#00b0f0" },
        { "Id": 1047, "Type": 0x79F, "Index": 41, "Name": "VersionSegment", "Color": "#ededed" },
        { "Id": 1048, "Type": 0x79F, "Index": 40, "Name": "", "Color": "#ededed" },
        { "Id": 1049, "Type": 0x79F, "Index": 55, "Name": "CanProtocoIVersion", "Color": "#8ea9db" },
        { "Id": 1050, "Type": 0x79F, "Index": 54, "Name": "", "Color": "#8ea9db" },
        { "Id": 1051, "Type": 0x79F, "Index": 53, "Name": "", "Color": "#8ea9db" },
        { "Id": 1052, "Type": 0x79F, "Index": 52, "Name": "", "Color": "#8ea9db" },
        { "Id": 1053, "Type": 0x79F, "Index": 51, "Name": "", "Color": "#8ea9db" },
        { "Id": 1054, "Type": 0x79F, "Index": 50, "Name": "", "Color": "#8ea9db" },
        { "Id": 1055, "Type": 0x79F, "Index": 49, "Name": "", "Color": "#8ea9db" },
        { "Id": 1056, "Type": 0x79F, "Index": 48, "Name": "", "Color": "#8ea9db" },
        { "Id": 1057, "Type": 0x79F, "Index": 63, "Name": "", "Color": "" },
        { "Id": 1058, "Type": 0x79F, "Index": 62, "Name": "", "Color": "" },
        { "Id": 1059, "Type": 0x79F, "Index": 61, "Name": "", "Color": "" },
        { "Id": 1060, "Type": 0x79F, "Index": 60, "Name": "", "Color": "" },
        { "Id": 1061, "Type": 0x79F, "Index": 59, "Name": "", "Color": "" },
        { "Id": 1062, "Type": 0x79F, "Index": 58, "Name": "", "Color": "" },
        { "Id": 1063, "Type": 0x79F, "Index": 57, "Name": "", "Color": "" },
        { "Id": 1064, "Type": 0x79F, "Index": 56, "Name": "", "Color": "" },

        { "Id": 2001, "Type": 0x7A0, "Index": 7, "Name": "ObstacleNumber", "Color": "#9bc2e6" },
        { "Id": 2002, "Type": 0x7A0, "Index": 6, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2003, "Type": 0x7A0, "Index": 5, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2004, "Type": 0x7A0, "Index": 4, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2005, "Type": 0x7A0, "Index": 3, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2006, "Type": 0x7A0, "Index": 2, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2007, "Type": 0x7A0, "Index": 1, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2008, "Type": 0x7A0, "Index": 0, "Name": "", "Color": "#9bc2e6" },
        { "Id": 2009, "Type": 0x7A0, "Index": 15, "Name": "TimeID", "Color": "#f8cbad" },
        { "Id": 2010, "Type": 0x7A0, "Index": 14, "Name": "", "Color": "#f8cbad" },
        { "Id": 2011, "Type": 0x7A0, "Index": 13, "Name": "", "Color": "#f8cbad" },
        { "Id": 2012, "Type": 0x7A0, "Index": 12, "Name": "", "Color": "#f8cbad" },
        { "Id": 2013, "Type": 0x7A0, "Index": 11, "Name": "", "Color": "#f8cbad" },
        { "Id": 2014, "Type": 0x7A0, "Index": 10, "Name": "", "Color": "#f8cbad" },
        { "Id": 2015, "Type": 0x7A0, "Index": 9, "Name": "", "Color": "#f8cbad" },
        { "Id": 2016, "Type": 0x7A0, "Index": 8, "Name": "", "Color": "#f8cbad" },
        { "Id": 2017, "Type": 0x7A0, "Index": 23, "Name": "", "Color": "#ffccff" },
        { "Id": 2018, "Type": 0x7A0, "Index": 22, "Name": "", "Color": "#ffccff" },
        { "Id": 2019, "Type": 0x7A0, "Index": 21, "Name": "", "Color": "#ffccff" },
        { "Id": 2020, "Type": 0x7A0, "Index": 20, "Name": "", "Color": "#ffccff" },
        { "Id": 2021, "Type": 0x7A0, "Index": 19, "Name": "", "Color": "#ffccff" },
        { "Id": 2022, "Type": 0x7A0, "Index": 18, "Name": "", "Color": "#ffccff" },
        { "Id": 2023, "Type": 0x7A0, "Index": 17, "Name": "", "Color": "#ffccff" },
        { "Id": 2024, "Type": 0x7A0, "Index": 16, "Name": "", "Color": "#ffccff" },
        { "Id": 2025, "Type": 0x7A0, "Index": 31, "Name": "", "Color": "" },
        { "Id": 2026, "Type": 0x7A0, "Index": 30, "Name": "", "Color": "" },
        { "Id": 2027, "Type": 0x7A0, "Index": 29, "Name": "YawAngle", "Color": "#ffccff" },
        { "Id": 2028, "Type": 0x7A0, "Index": 28, "Name": "", "Color": "#ffccff" },
        { "Id": 2029, "Type": 0x7A0, "Index": 27, "Name": "", "Color": "#ffccff" },
        { "Id": 2030, "Type": 0x7A0, "Index": 26, "Name": "", "Color": "#ffccff" },
        { "Id": 2031, "Type": 0x7A0, "Index": 25, "Name": "", "Color": "#ffccff" },
        { "Id": 2032, "Type": 0x7A0, "Index": 24, "Name": "", "Color": "#ffccff" },
        { "Id": 2033, "Type": 0x7A0, "Index": 39, "Name": "", "Color": "#92d050" },
        { "Id": 2034, "Type": 0x7A0, "Index": 38, "Name": "", "Color": "#92d050" },
        { "Id": 2035, "Type": 0x7A0, "Index": 37, "Name": "", "Color": "#92d050" },
        { "Id": 2036, "Type": 0x7A0, "Index": 36, "Name": "", "Color": "#92d050" },
        { "Id": 2037, "Type": 0x7A0, "Index": 35, "Name": "", "Color": "#92d050" },
        { "Id": 2038, "Type": 0x7A0, "Index": 34, "Name": "", "Color": "#92d050" },
        { "Id": 2039, "Type": 0x7A0, "Index": 33, "Name": "", "Color": "#92d050" },
        { "Id": 2040, "Type": 0x7A0, "Index": 32, "Name": "", "Color": "#92d050" },
        { "Id": 2041, "Type": 0x7A0, "Index": 47, "Name": "", "Color": "#ffc000" },
        { "Id": 2042, "Type": 0x7A0, "Index": 46, "Name": "", "Color": "#ffc000" },
        { "Id": 2043, "Type": 0x7A0, "Index": 45, "Name": "", "Color": "#ffc000" },
        { "Id": 2044, "Type": 0x7A0, "Index": 44, "Name": "", "Color": "#ffc000" },
        { "Id": 2045, "Type": 0x7A0, "Index": 43, "Name": "PitchAngle", "Color": "#92d050" },
        { "Id": 2046, "Type": 0x7A0, "Index": 42, "Name": "", "Color": "#92d050" },
        { "Id": 2047, "Type": 0x7A0, "Index": 41, "Name": "", "Color": "#92d050" },
        { "Id": 2048, "Type": 0x7A0, "Index": 40, "Name": "", "Color": "#92d050" },
        { "Id": 2049, "Type": 0x7A0, "Index": 55, "Name": "RotationAngle", "Color": "#ffc000" },
        { "Id": 2050, "Type": 0x7A0, "Index": 54, "Name": "", "Color": "#ffc000" },
        { "Id": 2051, "Type": 0x7A0, "Index": 53, "Name": "", "Color": "#ffc000" },
        { "Id": 2052, "Type": 0x7A0, "Index": 52, "Name": "", "Color": "#ffc000" },
        { "Id": 2053, "Type": 0x7A0, "Index": 51, "Name": "", "Color": "#ffc000" },
        { "Id": 2054, "Type": 0x7A0, "Index": 50, "Name": "", "Color": "#ffc000" },
        { "Id": 2055, "Type": 0x7A0, "Index": 49, "Name": "", "Color": "#ffc000" },
        { "Id": 2056, "Type": 0x7A0, "Index": 48, "Name": "", "Color": "#ffc000" },
        { "Id": 2057, "Type": 0x7A0, "Index": 63, "Name": "", "Color": "" },
        { "Id": 2058, "Type": 0x7A0, "Index": 62, "Name": "", "Color": "" },
        { "Id": 2059, "Type": 0x7A0, "Index": 61, "Name": "", "Color": "" },
        { "Id": 2060, "Type": 0x7A0, "Index": 60, "Name": "HMWAlarm Threshold", "Color": "#ff99cc" },
        { "Id": 2061, "Type": 0x7A0, "Index": 59, "Name": "", "Color": "#ff99cc" },
        { "Id": 2062, "Type": 0x7A0, "Index": 58, "Name": "", "Color": "#ff99cc" },
        { "Id": 2063, "Type": 0x7A0, "Index": 57, "Name": "", "Color": "#ff99cc" },
        { "Id": 2064, "Type": 0x7A0, "Index": 56, "Name": "", "Color": "#ff99cc" },

        { "Id": 3001, "Type": 0x7A1, "Index": 7, "Name": "ObstacleID", "Color": "#ff66cc" },
        { "Id": 3002, "Type": 0x7A1, "Index": 6, "Name": "", "Color": "#ff66cc" },
        { "Id": 3003, "Type": 0x7A1, "Index": 5, "Name": "", "Color": "#ff66cc" },
        { "Id": 3004, "Type": 0x7A1, "Index": 4, "Name": "", "Color": "#ff66cc" },
        { "Id": 3005, "Type": 0x7A1, "Index": 3, "Name": "", "Color": "#ff66cc" },
        { "Id": 3006, "Type": 0x7A1, "Index": 2, "Name": "", "Color": "#ff66cc" },
        { "Id": 3007, "Type": 0x7A1, "Index": 1, "Name": "", "Color": "#ff66cc" },
        { "Id": 3008, "Type": 0x7A1, "Index": 0, "Name": "", "Color": "#ff66cc" },
        { "Id": 3009, "Type": 0x7A1, "Index": 15, "Name": "", "Color": "" },
        { "Id": 3010, "Type": 0x7A1, "Index": 14, "Name": "", "Color": "" },
        { "Id": 3011, "Type": 0x7A1, "Index": 13, "Name": "TrackNumber", "Color": "#f8cbad" },
        { "Id": 3012, "Type": 0x7A1, "Index": 12, "Name": "", "Color": "#f8cbad" },
        { "Id": 3013, "Type": 0x7A1, "Index": 11, "Name": "", "Color": "#f8cbad" },
        { "Id": 3014, "Type": 0x7A1, "Index": 10, "Name": "", "Color": "#f8cbad" },
        { "Id": 3015, "Type": 0x7A1, "Index": 9, "Name": "", "Color": "#f8cbad" },
        { "Id": 3016, "Type": 0x7A1, "Index": 8, "Name": "", "Color": "#f8cbad" },
        { "Id": 3017, "Type": 0x7A1, "Index": 23, "Name": "", "Color": "#ffd966" },
        { "Id": 3018, "Type": 0x7A1, "Index": 22, "Name": "", "Color": "#ffd966" },
        { "Id": 3019, "Type": 0x7A1, "Index": 21, "Name": "", "Color": "#ffd966" },
        { "Id": 3020, "Type": 0x7A1, "Index": 20, "Name": "", "Color": "#ffd966" },
        { "Id": 3021, "Type": 0x7A1, "Index": 19, "Name": "", "Color": "#ffd966" },
        { "Id": 3022, "Type": 0x7A1, "Index": 18, "Name": "", "Color": "#ffd966" },
        { "Id": 3023, "Type": 0x7A1, "Index": 17, "Name": "", "Color": "#ffd966" },
        { "Id": 3024, "Type": 0x7A1, "Index": 16, "Name": "", "Color": "#ffd966" },
        { "Id": 3025, "Type": 0x7A1, "Index": 31, "Name": "", "Color": "#8ea9db" },
        { "Id": 3026, "Type": 0x7A1, "Index": 30, "Name": "", "Color": "#8ea9db" },
        { "Id": 3027, "Type": 0x7A1, "Index": 29, "Name": "", "Color": "#8ea9db" },
        { "Id": 3028, "Type": 0x7A1, "Index": 28, "Name": "", "Color": "#8ea9db" },
        { "Id": 3029, "Type": 0x7A1, "Index": 27, "Name": "ObstacleWidth", "Color": "#ffd966" },
        { "Id": 3030, "Type": 0x7A1, "Index": 26, "Name": "", "Color": "#ffd966" },
        { "Id": 3031, "Type": 0x7A1, "Index": 25, "Name": "", "Color": "#ffd966" },
        { "Id": 3032, "Type": 0x7A1, "Index": 24, "Name": "", "Color": "#ffd966" },
        { "Id": 3033, "Type": 0x7A1, "Index": 39, "Name": "ObstacleHeight", "Color": "#8ea9db" },
        { "Id": 3034, "Type": 0x7A1, "Index": 38, "Name": "", "Color": "#8ea9db" },
        { "Id": 3035, "Type": 0x7A1, "Index": 37, "Name": "", "Color": "#8ea9db" },
        { "Id": 3036, "Type": 0x7A1, "Index": 36, "Name": "", "Color": "#8ea9db" },
        { "Id": 3037, "Type": 0x7A1, "Index": 35, "Name": "", "Color": "#8ea9db" },
        { "Id": 3038, "Type": 0x7A1, "Index": 34, "Name": "", "Color": "#8ea9db" },
        { "Id": 3039, "Type": 0x7A1, "Index": 33, "Name": "", "Color": "#8ea9db" },
        { "Id": 3040, "Type": 0x7A1, "Index": 32, "Name": "", "Color": "#8ea9db" },
        { "Id": 3041, "Type": 0x7A1, "Index": 47, "Name": "", "Color": "#a9d08e" },
        { "Id": 3042, "Type": 0x7A1, "Index": 46, "Name": "", "Color": "#a9d08e" },
        { "Id": 3043, "Type": 0x7A1, "Index": 45, "Name": "", "Color": "#a9d08e" },
        { "Id": 3044, "Type": 0x7A1, "Index": 44, "Name": "", "Color": "#a9d08e" },
        { "Id": 3045, "Type": 0x7A1, "Index": 43, "Name": "", "Color": "#a9d08e" },
        { "Id": 3046, "Type": 0x7A1, "Index": 42, "Name": "", "Color": "#a9d08e" },
        { "Id": 3047, "Type": 0x7A1, "Index": 41, "Name": "", "Color": "#a9d08e" },
        { "Id": 3048, "Type": 0x7A1, "Index": 40, "Name": "", "Color": "#a9d08e" },
        { "Id": 3049, "Type": 0x7A1, "Index": 55, "Name": "", "Color": "#00b0f0" },
        { "Id": 3050, "Type": 0x7A1, "Index": 54, "Name": "", "Color": "#00b0f0" },
        { "Id": 3051, "Type": 0x7A1, "Index": 53, "Name": "", "Color": "#00b0f0" },
        { "Id": 3052, "Type": 0x7A1, "Index": 52, "Name": "", "Color": "#00b0f0" },
        { "Id": 3053, "Type": 0x7A1, "Index": 51, "Name": "RelativeSpeedZ", "Color": "#a9d08e" },
        { "Id": 3054, "Type": 0x7A1, "Index": 50, "Name": "", "Color": "#a9d08e" },
        { "Id": 3055, "Type": 0x7A1, "Index": 49, "Name": "", "Color": "#a9d08e" },
        { "Id": 3056, "Type": 0x7A1, "Index": 48, "Name": "", "Color": "#a9d08e" },
        { "Id": 3057, "Type": 0x7A1, "Index": 63, "Name": "DistanceY", "Color": "#00b0f0" },
        { "Id": 3058, "Type": 0x7A1, "Index": 62, "Name": "", "Color": "#00b0f0" },
        { "Id": 3059, "Type": 0x7A1, "Index": 61, "Name": "", "Color": "#00b0f0" },
        { "Id": 3060, "Type": 0x7A1, "Index": 60, "Name": "", "Color": "#00b0f0" },
        { "Id": 3061, "Type": 0x7A1, "Index": 59, "Name": "", "Color": "#00b0f0" },
        { "Id": 3062, "Type": 0x7A1, "Index": 58, "Name": "", "Color": "#00b0f0" },
        { "Id": 3063, "Type": 0x7A1, "Index": 57, "Name": "", "Color": "#00b0f0" },
        { "Id": 3064, "Type": 0x7A1, "Index": 56, "Name": "", "Color": "#00b0f0" },

        { "Id": 4001, "Type": 0x7A2, "Index": 7, "Name": "", "Color": "#00b0f0" },
        { "Id": 4002, "Type": 0x7A2, "Index": 6, "Name": "", "Color": "#00b0f0" },
        { "Id": 4003, "Type": 0x7A2, "Index": 5, "Name": "", "Color": "#00b0f0" },
        { "Id": 4004, "Type": 0x7A2, "Index": 4, "Name": "", "Color": "#00b0f0" },
        { "Id": 4005, "Type": 0x7A2, "Index": 3, "Name": "", "Color": "#00b0f0" },
        { "Id": 4006, "Type": 0x7A2, "Index": 2, "Name": "", "Color": "#00b0f0" },
        { "Id": 4007, "Type": 0x7A2, "Index": 1, "Name": "", "Color": "#00b0f0" },
        { "Id": 4008, "Type": 0x7A2, "Index": 0, "Name": "", "Color": "#00b0f0" },
        { "Id": 4009, "Type": 0x7A2, "Index": 15, "Name": "", "Color": "" },
        { "Id": 4010, "Type": 0x7A2, "Index": 14, "Name": "DistanceX", "Color": "#00b0f0" },
        { "Id": 4011, "Type": 0x7A2, "Index": 13, "Name": "", "Color": "#00b0f0" },
        { "Id": 4012, "Type": 0x7A2, "Index": 12, "Name": "", "Color": "#00b0f0" },
        { "Id": 4013, "Type": 0x7A2, "Index": 11, "Name": "", "Color": "#00b0f0" },
        { "Id": 4014, "Type": 0x7A2, "Index": 10, "Name": "", "Color": "#00b0f0" },
        { "Id": 4015, "Type": 0x7A2, "Index": 9, "Name": "", "Color": "#00b0f0" },
        { "Id": 4016, "Type": 0x7A2, "Index": 8, "Name": "", "Color": "#00b0f0" },
        { "Id": 4017, "Type": 0x7A2, "Index": 23, "Name": "", "Color": "#f8cbad" },
        { "Id": 4018, "Type": 0x7A2, "Index": 22, "Name": "", "Color": "#f8cbad" },
        { "Id": 4019, "Type": 0x7A2, "Index": 21, "Name": "", "Color": "#f8cbad" },
        { "Id": 4020, "Type": 0x7A2, "Index": 20, "Name": "", "Color": "#f8cbad" },
        { "Id": 4021, "Type": 0x7A2, "Index": 19, "Name": "", "Color": "#f8cbad" },
        { "Id": 4022, "Type": 0x7A2, "Index": 18, "Name": "", "Color": "#f8cbad" },
        { "Id": 4023, "Type": 0x7A2, "Index": 17, "Name": "", "Color": "#f8cbad" },
        { "Id": 4024, "Type": 0x7A2, "Index": 16, "Name": "", "Color": "#f8cbad" },
        { "Id": 4025, "Type": 0x7A2, "Index": 31, "Name": "", "Color": "" },
        { "Id": 4026, "Type": 0x7A2, "Index": 30, "Name": "DistanceZ", "Color": "#f8cbad" },
        { "Id": 4027, "Type": 0x7A2, "Index": 29, "Name": "", "Color": "#f8cbad" },
        { "Id": 4028, "Type": 0x7A2, "Index": 28, "Name": "", "Color": "#f8cbad" },
        { "Id": 4029, "Type": 0x7A2, "Index": 27, "Name": "", "Color": "#f8cbad" },
        { "Id": 4030, "Type": 0x7A2, "Index": 26, "Name": "", "Color": "#f8cbad" },
        { "Id": 4031, "Type": 0x7A2, "Index": 25, "Name": "", "Color": "#f8cbad" },
        { "Id": 4032, "Type": 0x7A2, "Index": 24, "Name": "", "Color": "#f8cbad" },
        { "Id": 4033, "Type": 0x7A2, "Index": 39, "Name": "", "Color": "#9bc2e6" },
        { "Id": 4034, "Type": 0x7A2, "Index": 38, "Name": "", "Color": "#9bc2e6" },
        { "Id": 4035, "Type": 0x7A2, "Index": 37, "Name": "TTC", "Color": "#c6e0b4" },
        { "Id": 4036, "Type": 0x7A2, "Index": 36, "Name": "", "Color": "#c6e0b4" },
        { "Id": 4037, "Type": 0x7A2, "Index": 35, "Name": "", "Color": "#c6e0b4" },
        { "Id": 4038, "Type": 0x7A2, "Index": 34, "Name": "", "Color": "#c6e0b4" },
        { "Id": 4039, "Type": 0x7A2, "Index": 33, "Name": "", "Color": "#c6e0b4" },
        { "Id": 4040, "Type": 0x7A2, "Index": 32, "Name": "", "Color": "#c6e0b4" },
        { "Id": 4041, "Type": 0x7A2, "Index": 47, "Name": "", "Color": "" },
        { "Id": 4042, "Type": 0x7A2, "Index": 46, "Name": "", "Color": "" },
        { "Id": 4043, "Type": 0x7A2, "Index": 45, "Name": "", "Color": "" },
        { "Id": 4044, "Type": 0x7A2, "Index": 44, "Name": "", "Color": "" },
        { "Id": 4045, "Type": 0x7A2, "Index": 43, "Name": "HMW", "Color": "#9bc2e6" },
        { "Id": 4046, "Type": 0x7A2, "Index": 42, "Name": "", "Color": "#9bc2e6" },
        { "Id": 4047, "Type": 0x7A2, "Index": 41, "Name": "", "Color": "#9bc2e6" },
        { "Id": 4048, "Type": 0x7A2, "Index": 40, "Name": "", "Color": "#9bc2e6" },
        { "Id": 4049, "Type": 0x7A2, "Index": 55, "Name": "", "Color": "#ff9900" },
        { "Id": 4050, "Type": 0x7A2, "Index": 54, "Name": "", "Color": "#ff9900" },
        { "Id": 4051, "Type": 0x7A2, "Index": 53, "Name": "", "Color": "#ff9900" },
        { "Id": 4052, "Type": 0x7A2, "Index": 52, "Name": "", "Color": "#ff9900" },
        { "Id": 4053, "Type": 0x7A2, "Index": 51, "Name": "", "Color": "#ff9900" },
        { "Id": 4054, "Type": 0x7A2, "Index": 50, "Name": "", "Color": "#ff9900" },
        { "Id": 4055, "Type": 0x7A2, "Index": 49, "Name": "", "Color": "#ff9900" },
        { "Id": 4056, "Type": 0x7A2, "Index": 48, "Name": "", "Color": "#ff9900" },
        { "Id": 4057, "Type": 0x7A2, "Index": 63, "Name": "", "Color": "" },
        { "Id": 4058, "Type": 0x7A2, "Index": 62, "Name": "Obstacle Type", "Color": "#92d050" },
        { "Id": 4059, "Type": 0x7A2, "Index": 61, "Name": "", "Color": "#92d050" },
        { "Id": 4060, "Type": 0x7A2, "Index": 60, "Name": "", "Color": "#92d050" },
        { "Id": 4061, "Type": 0x7A2, "Index": 59, "Name": "", "Color": "#92d050" },
        { "Id": 4062, "Type": 0x7A2, "Index": 58, "Name": "CIPV", "Color": "#ffd966" },
        { "Id": 4063, "Type": 0x7A2, "Index": 57, "Name": "RelativeSpeedX", "Color": "#ff9900" },
        { "Id": 4064, "Type": 0x7A2, "Index": 56, "Name": "", "Color": "#ff9900" },

        { "Id": 5001, "Type": 0x7A3, "Index": 7, "Name": "", "Color": "" },
        { "Id": 5002, "Type": 0x7A3, "Index": 6, "Name": "", "Color": "" },
        { "Id": 5003, "Type": 0x7A3, "Index": 5, "Name": "LeftLaneStyle", "Color": "#f8cbad" },
        { "Id": 5004, "Type": 0x7A3, "Index": 4, "Name": "", "Color": "#f8cbad" },
        { "Id": 5005, "Type": 0x7A3, "Index": 3, "Name": "LeftLaneStatus", "Color": "#9bc2e6" },
        { "Id": 5006, "Type": 0x7A3, "Index": 2, "Name": "", "Color": "#9bc2e6" },
        { "Id": 5007, "Type": 0x7A3, "Index": 1, "Name": "", "Color": "#9bc2e6" },
        { "Id": 5008, "Type": 0x7A3, "Index": 0, "Name": "", "Color": "#9bc2e6" },
        { "Id": 5009, "Type": 0x7A3, "Index": 15, "Name": "", "Color": "" },
        { "Id": 5010, "Type": 0x7A3, "Index": 14, "Name": "", "Color": "" },
        { "Id": 5011, "Type": 0x7A3, "Index": 13, "Name": "RightLaneStyle", "Color": "#ff99cc" },
        { "Id": 5012, "Type": 0x7A3, "Index": 12, "Name": "", "Color": "#ff99cc" },
        { "Id": 5013, "Type": 0x7A3, "Index": 11, "Name": "RightLaneStatus", "Color": "#92d050" },
        { "Id": 5014, "Type": 0x7A3, "Index": 10, "Name": "", "Color": "#92d050" },
        { "Id": 5015, "Type": 0x7A3, "Index": 9, "Name": "", "Color": "#92d050" },
        { "Id": 5016, "Type": 0x7A3, "Index": 8, "Name": "", "Color": "#92d050" },
        { "Id": 5017, "Type": 0x7A3, "Index": 23, "Name": "CarDepth", "Color": "#f4b084" },
        { "Id": 5018, "Type": 0x7A3, "Index": 22, "Name": "", "Color": "#f4b084" },
        { "Id": 5019, "Type": 0x7A3, "Index": 21, "Name": "", "Color": "#f4b084" },
        { "Id": 5020, "Type": 0x7A3, "Index": 20, "Name": "", "Color": "#f4b084" },
        { "Id": 5021, "Type": 0x7A3, "Index": 19, "Name": "", "Color": "#f4b084" },
        { "Id": 5022, "Type": 0x7A3, "Index": 18, "Name": "", "Color": "#f4b084" },
        { "Id": 5023, "Type": 0x7A3, "Index": 17, "Name": "", "Color": "#f4b084" },
        { "Id": 5024, "Type": 0x7A3, "Index": 16, "Name": "", "Color": "#f4b084" },
        { "Id": 5025, "Type": 0x7A3, "Index": 31, "Name": "", "Color": "#00b050" },
        { "Id": 5026, "Type": 0x7A3, "Index": 30, "Name": "", "Color": "#00b050" },
        { "Id": 5027, "Type": 0x7A3, "Index": 29, "Name": "", "Color": "#00b050" },
        { "Id": 5028, "Type": 0x7A3, "Index": 28, "Name": "", "Color": "#00b050" },
        { "Id": 5029, "Type": 0x7A3, "Index": 27, "Name": "", "Color": "#00b050" },
        { "Id": 5030, "Type": 0x7A3, "Index": 26, "Name": "", "Color": "#00b050" },
        { "Id": 5031, "Type": 0x7A3, "Index": 25, "Name": "", "Color": "#00b050" },
        { "Id": 5032, "Type": 0x7A3, "Index": 24, "Name": "", "Color": "#00b050" },
        { "Id": 5033, "Type": 0x7A3, "Index": 39, "Name": "", "Color": "" },
        { "Id": 5034, "Type": 0x7A3, "Index": 38, "Name": "", "Color": "" },
        { "Id": 5035, "Type": 0x7A3, "Index": 37, "Name": "", "Color": "" },
        { "Id": 5036, "Type": 0x7A3, "Index": 36, "Name": "", "Color": "" },
        { "Id": 5037, "Type": 0x7A3, "Index": 35, "Name": "", "Color": "" },
        { "Id": 5038, "Type": 0x7A3, "Index": 34, "Name": "", "Color": "" },
        { "Id": 5039, "Type": 0x7A3, "Index": 33, "Name": "SpeedOfRushLane", "Color": "#00b050" },
        { "Id": 5040, "Type": 0x7A3, "Index": 32, "Name": "", "Color": "#00b050" },
        { "Id": 5041, "Type": 0x7A3, "Index": 47, "Name": "", "Color": "" },
        { "Id": 5042, "Type": 0x7A3, "Index": 46, "Name": "", "Color": "" },
        { "Id": 5043, "Type": 0x7A3, "Index": 45, "Name": "", "Color": "" },
        { "Id": 5044, "Type": 0x7A3, "Index": 44, "Name": "", "Color": "" },
        { "Id": 5045, "Type": 0x7A3, "Index": 43, "Name": "", "Color": "" },
        { "Id": 5046, "Type": 0x7A3, "Index": 42, "Name": "", "Color": "" },
        { "Id": 5047, "Type": 0x7A3, "Index": 41, "Name": "", "Color": "" },
        { "Id": 5048, "Type": 0x7A3, "Index": 40, "Name": "", "Color": "" },
        { "Id": 5049, "Type": 0x7A3, "Index": 55, "Name": "", "Color": "" },
        { "Id": 5050, "Type": 0x7A3, "Index": 54, "Name": "", "Color": "" },
        { "Id": 5051, "Type": 0x7A3, "Index": 53, "Name": "", "Color": "" },
        { "Id": 5052, "Type": 0x7A3, "Index": 52, "Name": "", "Color": "" },
        { "Id": 5053, "Type": 0x7A3, "Index": 51, "Name": "", "Color": "" },
        { "Id": 5054, "Type": 0x7A3, "Index": 50, "Name": "", "Color": "" },
        { "Id": 5055, "Type": 0x7A3, "Index": 49, "Name": "", "Color": "" },
        { "Id": 5056, "Type": 0x7A3, "Index": 48, "Name": "", "Color": "" },
        { "Id": 5057, "Type": 0x7A3, "Index": 63, "Name": "", "Color": "" },
        { "Id": 5058, "Type": 0x7A3, "Index": 62, "Name": "", "Color": "" },
        { "Id": 5059, "Type": 0x7A3, "Index": 61, "Name": "", "Color": "" },
        { "Id": 5060, "Type": 0x7A3, "Index": 60, "Name": "", "Color": "" },
        { "Id": 5061, "Type": 0x7A3, "Index": 59, "Name": "", "Color": "" },
        { "Id": 5062, "Type": 0x7A3, "Index": 58, "Name": "", "Color": "" },
        { "Id": 5063, "Type": 0x7A3, "Index": 57, "Name": "", "Color": "" },
        { "Id": 5064, "Type": 0x7A3, "Index": 56, "Name": "", "Color": "" },

        { "Id": 6001, "Type": 0x7A4, "Index": 7, "Name": "", "Color": "#ff9900" },
        { "Id": 6002, "Type": 0x7A4, "Index": 6, "Name": "", "Color": "#ff9900" },
        { "Id": 6003, "Type": 0x7A4, "Index": 5, "Name": "", "Color": "#ff9900" },
        { "Id": 6004, "Type": 0x7A4, "Index": 4, "Name": "", "Color": "#ff9900" },
        { "Id": 6005, "Type": 0x7A4, "Index": 3, "Name": "", "Color": "#ff9900" },
        { "Id": 6006, "Type": 0x7A4, "Index": 2, "Name": "", "Color": "#ff9900" },
        { "Id": 6007, "Type": 0x7A4, "Index": 1, "Name": "", "Color": "#ff9900" },
        { "Id": 6008, "Type": 0x7A4, "Index": 0, "Name": "", "Color": "#ff9900" },
        { "Id": 6009, "Type": 0x7A4, "Index": 15, "Name": "C0", "Color": "#ff9900" },
        { "Id": 6010, "Type": 0x7A4, "Index": 14, "Name": "", "Color": "#ff9900" },
        { "Id": 6011, "Type": 0x7A4, "Index": 13, "Name": "", "Color": "#ff9900" },
        { "Id": 6012, "Type": 0x7A4, "Index": 12, "Name": "", "Color": "#ff9900" },
        { "Id": 6013, "Type": 0x7A4, "Index": 11, "Name": "", "Color": "#ff9900" },
        { "Id": 6014, "Type": 0x7A4, "Index": 10, "Name": "", "Color": "#ff9900" },
        { "Id": 6015, "Type": 0x7A4, "Index": 9, "Name": "", "Color": "#ff9900" },
        { "Id": 6016, "Type": 0x7A4, "Index": 8, "Name": "", "Color": "#ff9900" },
        { "Id": 6017, "Type": 0x7A4, "Index": 23, "Name": "", "Color": "#70ad47" },
        { "Id": 6018, "Type": 0x7A4, "Index": 22, "Name": "", "Color": "#70ad47" },
        { "Id": 6019, "Type": 0x7A4, "Index": 21, "Name": "", "Color": "#70ad47" },
        { "Id": 6020, "Type": 0x7A4, "Index": 20, "Name": "", "Color": "#70ad47" },
        { "Id": 6021, "Type": 0x7A4, "Index": 19, "Name": "", "Color": "#70ad47" },
        { "Id": 6022, "Type": 0x7A4, "Index": 18, "Name": "", "Color": "#70ad47" },
        { "Id": 6023, "Type": 0x7A4, "Index": 17, "Name": "", "Color": "#70ad47" },
        { "Id": 6024, "Type": 0x7A4, "Index": 16, "Name": "", "Color": "#70ad47" },
        { "Id": 6025, "Type": 0x7A4, "Index": 31, "Name": "C1", "Color": "#70ad47" },
        { "Id": 6026, "Type": 0x7A4, "Index": 30, "Name": "", "Color": "#70ad47" },
        { "Id": 6027, "Type": 0x7A4, "Index": 29, "Name": "", "Color": "#70ad47" },
        { "Id": 6028, "Type": 0x7A4, "Index": 28, "Name": "", "Color": "#70ad47" },
        { "Id": 6029, "Type": 0x7A4, "Index": 27, "Name": "", "Color": "#70ad47" },
        { "Id": 6030, "Type": 0x7A4, "Index": 26, "Name": "", "Color": "#70ad47" },
        { "Id": 6031, "Type": 0x7A4, "Index": 25, "Name": "", "Color": "#70ad47" },
        { "Id": 6032, "Type": 0x7A4, "Index": 24, "Name": "", "Color": "#70ad47" },
        { "Id": 6033, "Type": 0x7A4, "Index": 39, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6034, "Type": 0x7A4, "Index": 38, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6035, "Type": 0x7A4, "Index": 37, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6036, "Type": 0x7A4, "Index": 36, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6037, "Type": 0x7A4, "Index": 35, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6038, "Type": 0x7A4, "Index": 34, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6039, "Type": 0x7A4, "Index": 33, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6040, "Type": 0x7A4, "Index": 32, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6041, "Type": 0x7A4, "Index": 47, "Name": "C2", "Color": "#b4c6e7" },
        { "Id": 6042, "Type": 0x7A4, "Index": 46, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6043, "Type": 0x7A4, "Index": 45, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6044, "Type": 0x7A4, "Index": 44, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6045, "Type": 0x7A4, "Index": 43, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6046, "Type": 0x7A4, "Index": 42, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6047, "Type": 0x7A4, "Index": 41, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6048, "Type": 0x7A4, "Index": 40, "Name": "", "Color": "#b4c6e7" },
        { "Id": 6049, "Type": 0x7A4, "Index": 55, "Name": "", "Color": "#1e68f1" },
        { "Id": 6050, "Type": 0x7A4, "Index": 54, "Name": "", "Color": "#1e68f1" },
        { "Id": 6051, "Type": 0x7A4, "Index": 53, "Name": "", "Color": "#1e68f1" },
        { "Id": 6052, "Type": 0x7A4, "Index": 52, "Name": "", "Color": "#1e68f1" },
        { "Id": 6053, "Type": 0x7A4, "Index": 51, "Name": "", "Color": "#1e68f1" },
        { "Id": 6054, "Type": 0x7A4, "Index": 50, "Name": "", "Color": "#1e68f1" },
        { "Id": 6055, "Type": 0x7A4, "Index": 49, "Name": "", "Color": "#1e68f1" },
        { "Id": 6056, "Type": 0x7A4, "Index": 48, "Name": "", "Color": "#1e68f1" },
        { "Id": 6057, "Type": 0x7A4, "Index": 63, "Name": "C3", "Color": "#1e68f1" },
        { "Id": 6058, "Type": 0x7A4, "Index": 62, "Name": "", "Color": "#1e68f1" },
        { "Id": 6059, "Type": 0x7A4, "Index": 61, "Name": "", "Color": "#1e68f1" },
        { "Id": 6060, "Type": 0x7A4, "Index": 60, "Name": "", "Color": "#1e68f1" },
        { "Id": 6061, "Type": 0x7A4, "Index": 59, "Name": "", "Color": "#1e68f1" },
        { "Id": 6062, "Type": 0x7A4, "Index": 58, "Name": "", "Color": "#1e68f1" },
        { "Id": 6063, "Type": 0x7A4, "Index": 57, "Name": "", "Color": "#1e68f1" },
        { "Id": 6064, "Type": 0x7A4, "Index": 56, "Name": "", "Color": "#1e68f1" },

        { "Id": 7001, "Type": 0x7A5, "Index": 7, "Name": "", "Color": "#a9d08e" },
        { "Id": 7002, "Type": 0x7A5, "Index": 6, "Name": "", "Color": "#a9d08e" },
        { "Id": 7003, "Type": 0x7A5, "Index": 5, "Name": "", "Color": "#a9d08e" },
        { "Id": 7004, "Type": 0x7A5, "Index": 4, "Name": "", "Color": "#a9d08e" },
        { "Id": 7005, "Type": 0x7A5, "Index": 3, "Name": "", "Color": "#a9d08e" },
        { "Id": 7006, "Type": 0x7A5, "Index": 2, "Name": "", "Color": "#a9d08e" },
        { "Id": 7007, "Type": 0x7A5, "Index": 1, "Name": "", "Color": "#a9d08e" },
        { "Id": 7008, "Type": 0x7A5, "Index": 0, "Name": "", "Color": "#a9d08e" },
        { "Id": 7009, "Type": 0x7A5, "Index": 15, "Name": "C0", "Color": "#a9d08e" },
        { "Id": 7010, "Type": 0x7A5, "Index": 14, "Name": "", "Color": "#a9d08e" },
        { "Id": 7011, "Type": 0x7A5, "Index": 13, "Name": "", "Color": "#a9d08e" },
        { "Id": 7012, "Type": 0x7A5, "Index": 12, "Name": "", "Color": "#a9d08e" },
        { "Id": 7013, "Type": 0x7A5, "Index": 11, "Name": "", "Color": "#a9d08e" },
        { "Id": 7014, "Type": 0x7A5, "Index": 10, "Name": "", "Color": "#a9d08e" },
        { "Id": 7015, "Type": 0x7A5, "Index": 9, "Name": "", "Color": "#a9d08e" },
        { "Id": 7016, "Type": 0x7A5, "Index": 8, "Name": "", "Color": "#a9d08e" },
        { "Id": 7017, "Type": 0x7A5, "Index": 23, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7018, "Type": 0x7A5, "Index": 22, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7019, "Type": 0x7A5, "Index": 21, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7020, "Type": 0x7A5, "Index": 20, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7021, "Type": 0x7A5, "Index": 19, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7022, "Type": 0x7A5, "Index": 18, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7023, "Type": 0x7A5, "Index": 17, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7024, "Type": 0x7A5, "Index": 16, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7025, "Type": 0x7A5, "Index": 31, "Name": "C1", "Color": "#b4c6e7" },
        { "Id": 7026, "Type": 0x7A5, "Index": 30, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7027, "Type": 0x7A5, "Index": 29, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7028, "Type": 0x7A5, "Index": 28, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7029, "Type": 0x7A5, "Index": 27, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7030, "Type": 0x7A5, "Index": 26, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7031, "Type": 0x7A5, "Index": 25, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7032, "Type": 0x7A5, "Index": 24, "Name": "", "Color": "#b4c6e7" },
        { "Id": 7033, "Type": 0x7A5, "Index": 39, "Name": "", "Color": "#f4b084" },
        { "Id": 7034, "Type": 0x7A5, "Index": 38, "Name": "", "Color": "#f4b084" },
        { "Id": 7035, "Type": 0x7A5, "Index": 37, "Name": "", "Color": "#f4b084" },
        { "Id": 7036, "Type": 0x7A5, "Index": 36, "Name": "", "Color": "#f4b084" },
        { "Id": 7037, "Type": 0x7A5, "Index": 35, "Name": "", "Color": "#f4b084" },
        { "Id": 7038, "Type": 0x7A5, "Index": 34, "Name": "", "Color": "#f4b084" },
        { "Id": 7039, "Type": 0x7A5, "Index": 33, "Name": "", "Color": "#f4b084" },
        { "Id": 7040, "Type": 0x7A5, "Index": 32, "Name": "", "Color": "#f4b084" },
        { "Id": 7041, "Type": 0x7A5, "Index": 47, "Name": "C2", "Color": "#f4b084" },
        { "Id": 7042, "Type": 0x7A5, "Index": 46, "Name": "", "Color": "#f4b084" },
        { "Id": 7043, "Type": 0x7A5, "Index": 45, "Name": "", "Color": "#f4b084" },
        { "Id": 7044, "Type": 0x7A5, "Index": 44, "Name": "", "Color": "#f4b084" },
        { "Id": 7045, "Type": 0x7A5, "Index": 43, "Name": "", "Color": "#f4b084" },
        { "Id": 7046, "Type": 0x7A5, "Index": 42, "Name": "", "Color": "#f4b084" },
        { "Id": 7047, "Type": 0x7A5, "Index": 41, "Name": "", "Color": "#f4b084" },
        { "Id": 7048, "Type": 0x7A5, "Index": 40, "Name": "", "Color": "#f4b084" },
        { "Id": 7049, "Type": 0x7A5, "Index": 55, "Name": "", "Color": "#ff99cc" },
        { "Id": 7050, "Type": 0x7A5, "Index": 54, "Name": "", "Color": "#ff99cc" },
        { "Id": 7051, "Type": 0x7A5, "Index": 53, "Name": "", "Color": "#ff99cc" },
        { "Id": 7052, "Type": 0x7A5, "Index": 52, "Name": "", "Color": "#ff99cc" },
        { "Id": 7053, "Type": 0x7A5, "Index": 51, "Name": "", "Color": "#ff99cc" },
        { "Id": 7054, "Type": 0x7A5, "Index": 50, "Name": "", "Color": "#ff99cc" },
        { "Id": 7055, "Type": 0x7A5, "Index": 49, "Name": "", "Color": "#ff99cc" },
        { "Id": 7056, "Type": 0x7A5, "Index": 48, "Name": "", "Color": "#ff99cc" },
        { "Id": 7057, "Type": 0x7A5, "Index": 63, "Name": "C3", "Color": "#ff99cc" },
        { "Id": 7058, "Type": 0x7A5, "Index": 62, "Name": "", "Color": "#ff99cc" },
        { "Id": 7059, "Type": 0x7A5, "Index": 61, "Name": "", "Color": "#ff99cc" },
        { "Id": 7060, "Type": 0x7A5, "Index": 60, "Name": "", "Color": "#ff99cc" },
        { "Id": 7061, "Type": 0x7A5, "Index": 59, "Name": "", "Color": "#ff99cc" },
        { "Id": 7062, "Type": 0x7A5, "Index": 58, "Name": "", "Color": "#ff99cc" },
        { "Id": 7063, "Type": 0x7A5, "Index": 57, "Name": "", "Color": "#ff99cc" },
        { "Id": 7064, "Type": 0x7A5, "Index": 56, "Name": "", "Color": "#ff99cc" },

        { "Id": 8001, "Type": 0x7A6, "Index": 7, "Name": "", "Color": "#ff99cc" },
        { "Id": 8002, "Type": 0x7A6, "Index": 6, "Name": "", "Color": "#ff99cc" },
        { "Id": 8003, "Type": 0x7A6, "Index": 5, "Name": "", "Color": "#ff99cc" },
        { "Id": 8004, "Type": 0x7A6, "Index": 4, "Name": "", "Color": "#ff99cc" },
        { "Id": 8005, "Type": 0x7A6, "Index": 3, "Name": "", "Color": "#ff99cc" },
        { "Id": 8006, "Type": 0x7A6, "Index": 2, "Name": "", "Color": "#ff99cc" },
        { "Id": 8007, "Type": 0x7A6, "Index": 1, "Name": "", "Color": "#ff99cc" },
        { "Id": 8008, "Type": 0x7A6, "Index": 0, "Name": "", "Color": "#ff99cc" },
        { "Id": 8009, "Type": 0x7A6, "Index": 15, "Name": "C0", "Color": "#ff99cc" },
        { "Id": 8010, "Type": 0x7A6, "Index": 14, "Name": "", "Color": "#ff99cc" },
        { "Id": 8011, "Type": 0x7A6, "Index": 13, "Name": "", "Color": "#ff99cc" },
        { "Id": 8012, "Type": 0x7A6, "Index": 12, "Name": "", "Color": "#ff99cc" },
        { "Id": 8013, "Type": 0x7A6, "Index": 11, "Name": "", "Color": "#ff99cc" },
        { "Id": 8014, "Type": 0x7A6, "Index": 10, "Name": "", "Color": "#ff99cc" },
        { "Id": 8015, "Type": 0x7A6, "Index": 9, "Name": "", "Color": "#ff99cc" },
        { "Id": 8016, "Type": 0x7A6, "Index": 8, "Name": "", "Color": "#ff99cc" },
        { "Id": 8017, "Type": 0x7A6, "Index": 23, "Name": "", "Color": "#a9d08e" },
        { "Id": 8018, "Type": 0x7A6, "Index": 22, "Name": "", "Color": "#a9d08e" },
        { "Id": 8019, "Type": 0x7A6, "Index": 21, "Name": "", "Color": "#a9d08e" },
        { "Id": 8020, "Type": 0x7A6, "Index": 20, "Name": "", "Color": "#a9d08e" },
        { "Id": 8021, "Type": 0x7A6, "Index": 19, "Name": "", "Color": "#a9d08e" },
        { "Id": 8022, "Type": 0x7A6, "Index": 18, "Name": "", "Color": "#a9d08e" },
        { "Id": 8023, "Type": 0x7A6, "Index": 17, "Name": "", "Color": "#a9d08e" },
        { "Id": 8024, "Type": 0x7A6, "Index": 16, "Name": "", "Color": "#a9d08e" },
        { "Id": 8025, "Type": 0x7A6, "Index": 31, "Name": "C1", "Color": "#a9d08e" },
        { "Id": 8026, "Type": 0x7A6, "Index": 30, "Name": "", "Color": "#a9d08e" },
        { "Id": 8027, "Type": 0x7A6, "Index": 29, "Name": "", "Color": "#a9d08e" },
        { "Id": 8028, "Type": 0x7A6, "Index": 28, "Name": "", "Color": "#a9d08e" },
        { "Id": 8029, "Type": 0x7A6, "Index": 27, "Name": "", "Color": "#a9d08e" },
        { "Id": 8030, "Type": 0x7A6, "Index": 26, "Name": "", "Color": "#a9d08e" },
        { "Id": 8031, "Type": 0x7A6, "Index": 25, "Name": "", "Color": "#a9d08e" },
        { "Id": 8032, "Type": 0x7A6, "Index": 24, "Name": "", "Color": "#a9d08e" },
        { "Id": 8033, "Type": 0x7A6, "Index": 39, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8034, "Type": 0x7A6, "Index": 38, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8035, "Type": 0x7A6, "Index": 37, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8036, "Type": 0x7A6, "Index": 36, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8037, "Type": 0x7A6, "Index": 35, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8038, "Type": 0x7A6, "Index": 34, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8039, "Type": 0x7A6, "Index": 33, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8040, "Type": 0x7A6, "Index": 32, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8041, "Type": 0x7A6, "Index": 47, "Name": "C2", "Color": "#b4c6e7" },
        { "Id": 8042, "Type": 0x7A6, "Index": 46, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8043, "Type": 0x7A6, "Index": 45, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8044, "Type": 0x7A6, "Index": 44, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8045, "Type": 0x7A6, "Index": 43, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8046, "Type": 0x7A6, "Index": 42, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8047, "Type": 0x7A6, "Index": 41, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8048, "Type": 0x7A6, "Index": 40, "Name": "", "Color": "#b4c6e7" },
        { "Id": 8049, "Type": 0x7A6, "Index": 55, "Name": "", "Color": "#f8cbad" },
        { "Id": 8050, "Type": 0x7A6, "Index": 54, "Name": "", "Color": "#f8cbad" },
        { "Id": 8051, "Type": 0x7A6, "Index": 53, "Name": "", "Color": "#f8cbad" },
        { "Id": 8052, "Type": 0x7A6, "Index": 52, "Name": "", "Color": "#f8cbad" },
        { "Id": 8053, "Type": 0x7A6, "Index": 51, "Name": "", "Color": "#f8cbad" },
        { "Id": 8054, "Type": 0x7A6, "Index": 50, "Name": "", "Color": "#f8cbad" },
        { "Id": 8055, "Type": 0x7A6, "Index": 49, "Name": "", "Color": "#f8cbad" },
        { "Id": 8056, "Type": 0x7A6, "Index": 48, "Name": "", "Color": "#f8cbad" },
        { "Id": 8057, "Type": 0x7A6, "Index": 63, "Name": "C3", "Color": "#f8cbad" },
        { "Id": 8058, "Type": 0x7A6, "Index": 62, "Name": "", "Color": "#f8cbad" },
        { "Id": 8059, "Type": 0x7A6, "Index": 61, "Name": "", "Color": "#f8cbad" },
        { "Id": 8060, "Type": 0x7A6, "Index": 60, "Name": "", "Color": "#f8cbad" },
        { "Id": 8061, "Type": 0x7A6, "Index": 59, "Name": "", "Color": "#f8cbad" },
        { "Id": 8062, "Type": 0x7A6, "Index": 58, "Name": "", "Color": "#f8cbad" },
        { "Id": 8063, "Type": 0x7A6, "Index": 57, "Name": "", "Color": "#f8cbad" },
        { "Id": 8064, "Type": 0x7A6, "Index": 56, "Name": "", "Color": "#f8cbad" },

        { "Id": 9001, "Type": 0x7A7, "Index": 7, "Name": "", "Color": "#f8cbad" },
        { "Id": 9002, "Type": 0x7A7, "Index": 6, "Name": "", "Color": "#f8cbad" },
        { "Id": 9003, "Type": 0x7A7, "Index": 5, "Name": "", "Color": "#f8cbad" },
        { "Id": 9004, "Type": 0x7A7, "Index": 4, "Name": "", "Color": "#f8cbad" },
        { "Id": 9005, "Type": 0x7A7, "Index": 3, "Name": "", "Color": "#f8cbad" },
        { "Id": 9006, "Type": 0x7A7, "Index": 2, "Name": "", "Color": "#f8cbad" },
        { "Id": 9007, "Type": 0x7A7, "Index": 1, "Name": "", "Color": "#f8cbad" },
        { "Id": 9008, "Type": 0x7A7, "Index": 0, "Name": "", "Color": "#f8cbad" },
        { "Id": 9009, "Type": 0x7A7, "Index": 15, "Name": "C0", "Color": "#f8cbad" },
        { "Id": 9010, "Type": 0x7A7, "Index": 14, "Name": "", "Color": "#f8cbad" },
        { "Id": 9011, "Type": 0x7A7, "Index": 13, "Name": "", "Color": "#f8cbad" },
        { "Id": 9012, "Type": 0x7A7, "Index": 12, "Name": "", "Color": "#f8cbad" },
        { "Id": 9013, "Type": 0x7A7, "Index": 11, "Name": "", "Color": "#f8cbad" },
        { "Id": 9014, "Type": 0x7A7, "Index": 10, "Name": "", "Color": "#f8cbad" },
        { "Id": 9015, "Type": 0x7A7, "Index": 9, "Name": "", "Color": "#f8cbad" },
        { "Id": 9016, "Type": 0x7A7, "Index": 8, "Name": "", "Color": "#f8cbad" },
        { "Id": 9017, "Type": 0x7A7, "Index": 23, "Name": "", "Color": "#00b0f0" },
        { "Id": 9018, "Type": 0x7A7, "Index": 22, "Name": "", "Color": "#00b0f0" },
        { "Id": 9019, "Type": 0x7A7, "Index": 21, "Name": "", "Color": "#00b0f0" },
        { "Id": 9020, "Type": 0x7A7, "Index": 20, "Name": "", "Color": "#00b0f0" },
        { "Id": 9021, "Type": 0x7A7, "Index": 19, "Name": "", "Color": "#00b0f0" },
        { "Id": 9022, "Type": 0x7A7, "Index": 18, "Name": "", "Color": "#00b0f0" },
        { "Id": 9023, "Type": 0x7A7, "Index": 17, "Name": "", "Color": "#00b0f0" },
        { "Id": 9024, "Type": 0x7A7, "Index": 16, "Name": "", "Color": "#00b0f0" },
        { "Id": 9025, "Type": 0x7A7, "Index": 31, "Name": "C1", "Color": "#00b0f0" },
        { "Id": 9026, "Type": 0x7A7, "Index": 30, "Name": "", "Color": "#00b0f0" },
        { "Id": 9027, "Type": 0x7A7, "Index": 29, "Name": "", "Color": "#00b0f0" },
        { "Id": 9028, "Type": 0x7A7, "Index": 28, "Name": "", "Color": "#00b0f0" },
        { "Id": 9029, "Type": 0x7A7, "Index": 27, "Name": "", "Color": "#00b0f0" },
        { "Id": 9030, "Type": 0x7A7, "Index": 26, "Name": "", "Color": "#00b0f0" },
        { "Id": 9031, "Type": 0x7A7, "Index": 25, "Name": "", "Color": "#00b0f0" },
        { "Id": 9032, "Type": 0x7A7, "Index": 24, "Name": "", "Color": "#00b0f0" },
        { "Id": 9033, "Type": 0x7A7, "Index": 39, "Name": "", "Color": "#ffccff" },
        { "Id": 9034, "Type": 0x7A7, "Index": 38, "Name": "", "Color": "#ffccff" },
        { "Id": 9035, "Type": 0x7A7, "Index": 37, "Name": "", "Color": "#ffccff" },
        { "Id": 9036, "Type": 0x7A7, "Index": 36, "Name": "", "Color": "#ffccff" },
        { "Id": 9037, "Type": 0x7A7, "Index": 35, "Name": "", "Color": "#ffccff" },
        { "Id": 9038, "Type": 0x7A7, "Index": 34, "Name": "", "Color": "#ffccff" },
        { "Id": 9039, "Type": 0x7A7, "Index": 33, "Name": "", "Color": "#ffccff" },
        { "Id": 9040, "Type": 0x7A7, "Index": 32, "Name": "", "Color": "#ffccff" },
        { "Id": 9041, "Type": 0x7A7, "Index": 47, "Name": "C2", "Color": "#ffccff" },
        { "Id": 9042, "Type": 0x7A7, "Index": 46, "Name": "", "Color": "#ffccff" },
        { "Id": 9043, "Type": 0x7A7, "Index": 45, "Name": "", "Color": "#ffccff" },
        { "Id": 9044, "Type": 0x7A7, "Index": 44, "Name": "", "Color": "#ffccff" },
        { "Id": 9045, "Type": 0x7A7, "Index": 43, "Name": "", "Color": "#ffccff" },
        { "Id": 9046, "Type": 0x7A7, "Index": 42, "Name": "", "Color": "#ffccff" },
        { "Id": 9047, "Type": 0x7A7, "Index": 41, "Name": "", "Color": "#ffccff" },
        { "Id": 9048, "Type": 0x7A7, "Index": 40, "Name": "", "Color": "#ffccff" },
        { "Id": 9049, "Type": 0x7A7, "Index": 55, "Name": "", "Color": "#00b050" },
        { "Id": 9050, "Type": 0x7A7, "Index": 54, "Name": "", "Color": "#00b050" },
        { "Id": 9051, "Type": 0x7A7, "Index": 53, "Name": "", "Color": "#00b050" },
        { "Id": 9052, "Type": 0x7A7, "Index": 52, "Name": "", "Color": "#00b050" },
        { "Id": 9053, "Type": 0x7A7, "Index": 51, "Name": "", "Color": "#00b050" },
        { "Id": 9054, "Type": 0x7A7, "Index": 50, "Name": "", "Color": "#00b050" },
        { "Id": 9055, "Type": 0x7A7, "Index": 49, "Name": "", "Color": "#00b050" },
        { "Id": 9056, "Type": 0x7A7, "Index": 48, "Name": "", "Color": "#00b050" },
        { "Id": 9057, "Type": 0x7A7, "Index": 63, "Name": "C3", "Color": "#00b050" },
        { "Id": 9058, "Type": 0x7A7, "Index": 62, "Name": "", "Color": "#00b050" },
        { "Id": 9059, "Type": 0x7A7, "Index": 61, "Name": "", "Color": "#00b050" },
        { "Id": 9060, "Type": 0x7A7, "Index": 60, "Name": "", "Color": "#00b050" },
        { "Id": 9061, "Type": 0x7A7, "Index": 59, "Name": "", "Color": "#00b050" },
        { "Id": 9062, "Type": 0x7A7, "Index": 58, "Name": "", "Color": "#00b050" },
        { "Id": 9063, "Type": 0x7A7, "Index": 57, "Name": "", "Color": "#00b050" },
        { "Id": 9064, "Type": 0x7A7, "Index": 56, "Name": "", "Color": "#00b050" },
    ];

    public TypeMap: Map<number, string> = new Map([
        [-1, '无'],
        [0, '全部'],
        [0x79F, '0x79F'],
        [0x7A0, '0x7A0'],
        [0x7A1, '0x7A1'],
        [0x7A2, '0x7A2'],
        [0x7A3, '0x7A3'],
        [0x7A4, '0x7A4'],
        [0x7A5, '0x7A5'],
        [0x7A6, '0x7A6'],
        [0x7A7, '0x7A7'],
    ]);

    /**
    * 协议类型
    */
    public Type: Ref<number> = ref(-1);

    public Capacity: number = 64;

    public Datas: UnwrapNestedRefs<Array<ClientMessage.BinocularCameraProtocolData>> = reactive([]);

    public DataType: Ref<number> = ref(-1);
    public DataBits: Ref<Array<number>> = ref([]);

    public DocumentUrl: Ref<string> = ref('/static/BinocularCamera/协议解析.pdf');

    public ShowDocument: Ref<boolean> = ref(false);
    public ShowTool: Ref<boolean> = ref(false);

    public DataSource: Ref<string> = ref('Device');

    public SimulatedData: Array<ClientMessage.BinocularCameraProtocolData> = [
        new ClientMessage.BinocularCameraProtocolData(0x79F, [0x10, 0x81, 0x3F, 0x00, 0x00, 0x1A, 0x00, 0xB5], 247572168),
        new ClientMessage.BinocularCameraProtocolData(0x79F, [0x10, 0x81, 0x3F, 0x00, 0x00, 0x18, 0x00, 0xB5], 247573168),
        new ClientMessage.BinocularCameraProtocolData(0x79F, [0x10, 0x81, 0x3F, 0x00, 0x00, 0x1E, 0x00, 0xB5], 247569176),

        new ClientMessage.BinocularCameraProtocolData(0x7A0, [0x01, 0x55, 0xFF, 0x3F, 0xFF, 0xF7, 0x7F, 0x0A], 298739167),
        new ClientMessage.BinocularCameraProtocolData(0x7A0, [0x01, 0xB9, 0xFF, 0x3F, 0xFF, 0xF7, 0x7F, 0x0A], 298740170),
        new ClientMessage.BinocularCameraProtocolData(0x7A0, [0x01, 0x1D, 0xFF, 0x3F, 0xFF, 0xF7, 0x7F, 0x0A], 298741162),

        new ClientMessage.BinocularCameraProtocolData(0x7A1, [0x20, 0x3F, 0x79, 0xC0, 0x02, 0xD7, 0x37, 0x81], 25844622),
        new ClientMessage.BinocularCameraProtocolData(0x7A1, [0x20, 0x3F, 0x7B, 0xC0, 0x02, 0xD8, 0x37, 0x81], 25845625),
        new ClientMessage.BinocularCameraProtocolData(0x7A1, [0x20, 0x3F, 0x79, 0xC0, 0x02, 0xDA, 0x37, 0x81], 25846624),

        new ClientMessage.BinocularCameraProtocolData(0x7A2, [0xD4, 0x3F, 0x5F, 0x01, 0xBF, 0x00, 0xFF, 0x45], 112484884),
        new ClientMessage.BinocularCameraProtocolData(0x7A2, [0xD5, 0x3F, 0x5E, 0x01, 0xBF, 0x00, 0x00, 0x46], 112485896),
        new ClientMessage.BinocularCameraProtocolData(0x7A2, [0xD6, 0x3F, 0x5E, 0x01, 0xBF, 0x00, 0x00, 0x46], 112486882),

        new ClientMessage.BinocularCameraProtocolData(0x7A3, [0x00, 0x00, 0x0A, 0xFF, 0x03, 0x00, 0x00, 0x00], 157918914),
        new ClientMessage.BinocularCameraProtocolData(0x7A3, [0x00, 0x00, 0x0A, 0xFF, 0x03, 0x00, 0x00, 0x00], 157919921),
        new ClientMessage.BinocularCameraProtocolData(0x7A3, [0x00, 0x00, 0x0A, 0xFF, 0x03, 0x00, 0x00, 0x00], 157915919),

        new ClientMessage.BinocularCameraProtocolData(0x7A4, [0x93, 0x78, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 167519092),
        new ClientMessage.BinocularCameraProtocolData(0x7A4, [0x93, 0x78, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 167520092),
        new ClientMessage.BinocularCameraProtocolData(0x7A4, [0x93, 0x78, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 167521094),

        new ClientMessage.BinocularCameraProtocolData(0x7A5, [0x29, 0x79, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 171067727),
        new ClientMessage.BinocularCameraProtocolData(0x7A5, [0x29, 0x79, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 171068728),
        new ClientMessage.BinocularCameraProtocolData(0x7A5, [0x29, 0x79, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 171069721),

        new ClientMessage.BinocularCameraProtocolData(0x7A6, [0xD5, 0x86, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 171818811),
        new ClientMessage.BinocularCameraProtocolData(0x7A6, [0xD5, 0x86, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 171819802),
        new ClientMessage.BinocularCameraProtocolData(0x7A6, [0xD5, 0x86, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 171821801),

        new ClientMessage.BinocularCameraProtocolData(0x7A7, [0x6B, 0x87, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 172414075),
        new ClientMessage.BinocularCameraProtocolData(0x7A7, [0x6B, 0x87, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 172415072),
        new ClientMessage.BinocularCameraProtocolData(0x7A7, [0x6B, 0x87, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F], 172416075),
    ];

    public FormattedData: Ref<string> = ref('');

    public ShowParserReferences = ref(false);
    public ShowParserResults = ref(false);

    private watchStopHandles: Array<WatchStopHandle> = [];

    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetBlackBackground();
        TooltipComponent.Default.Clear();

        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        lock.Dispose();
    }

    public Receive(datas: Array<ClientMessage.BinocularCameraProtocolData>): void {
        if (this.DataSource.value == 'Simulate') {
            return;
        }

        const count = this.Datas.length + datas.length - this.Capacity;
        this.Datas.removeAt(0, count);
        this.Datas.addRange(datas);
    }

    private OnDataSourceChanged(): void {
        if (this.DataSource.value == 'Device') {
            this.OnDataSourceChangedToDevice();
        } else {
            this.OnDataSourceChangedToSimulation();
        }
    }

    private OnDataSourceChangedToDevice(): void {
        this.Datas.clear();
    }

    private OnDataSourceChangedToSimulation(): void {
        this.Datas.clear();
        this.Datas.addRange(this.SimulatedData.filter(data => this.Type.value == 0 || data.Id == this.Type.value));
    }

    public HiddenDomain = ref(false)
    public Resolve(data: ClientMessage.BinocularCameraProtocolData): void {
        this.HiddenDomain.value = !this.HiddenDomain.value
        this.ShowParserReferences.value = false;
        this.ShowParserResults.value = false;
        this.DefinitionConfigs.forEach((item)=>{
          item.Value = ''
        })

        this.DataBits.value.clear();        
        for (const byte of data.Data) {
            this.DataBits.value.addRange(Array.from(byte.toString(2).padStart(8, '0')).reverse().map(char => Number.parseInt(char)));
        }

        this.FormattedData.value = `0x${data.Id.toString(16).padStart(3, '0').toUpperCase()} - ` + data.Data.map(byte => byte.toString(16).padStart(2, '0').toUpperCase()).join(' ');

        this.DataType.value = data.Id;

        // CAN信号解析 - Motorola
        function ResolveMotorolaSingalValue(start: number, length: number, data: Array<number>): number {
            let merge = 0;
            let value = 0;

            const lsbBit = start & 7;
            const lsbByte = start >> 3;

            const msbByte = lsbByte - ((lsbBit + length - 1) >> 3);
            for (let index = msbByte; index < lsbByte + 1; index++) {
                merge += data[index] << ((lsbByte - index) << 3);
            }

            value = merge >> lsbBit;
            value = value & ((1 << length) - 1);

            return value;
        }

        // CAN信号解析 - Intel
        function ResolveIntelSingalValue(start: number, length: number, data: Array<number>): number {
            let merge = 0;
            let value = 0;

            const lsbBit = start & 7;
            const lsbByte = start >> 3;

            const msbByte = lsbByte + ((lsbBit + length - 1) >> 3);
            for (let index = msbByte; index > lsbByte - 1; index--) {
                merge += data[index] << ((index - lsbByte) << 3);
            }

            value = merge >> lsbBit;
            value = value & ((1 << length) - 1);

            return value;
        }

        const configs = this.DefinitionConfigs.filter(config => config.Type == this.DataType.value);
        for (const config of configs) {
            const start = config.StartIndex;
            const length = config.Length;
            const resolution = config.Resolution;
            const offset = config.Offset;

            const value = ResolveIntelSingalValue(start, length, data.Data) * resolution + offset;

            config.Reference = (Math.round(value * Math.pow(10, 12)) / Math.pow(10, 12)).toString();
        }
    }

    /**
     * 当前协议类型发生变化时
     * @param value 模块
     */
    private async OnTypeChangedAsync(value: number, previous: number): Promise<void> {
        this.Datas.clear();

        const request = new ClientMessage.BinocularCameraProtocolDataFilterUpdateRequest(BinocularCameraSettings.Default.DeviceIndex, value);
        await WebSocketComponent.Default.PostMessageAsync(request);

        if (this.DataSource.value == 'Simulate') {
            this.OnDataSourceChangedToSimulation();
        }
    }

    /**
     * 计算当前二进制Bit
     * @param index 配置索引
     */
    public CalculateBit(index: number): number {
        return index < this.DataBits.value.length ? this.DataBits.value[index] : 0;
    }

    public Convert(input: string, fromRadix: number, toRadix: number): string {
        return input == '' ? '' : Number.parseInt(input, fromRadix).toString(toRadix);
    }
}

/**
 *  应用组件
 */
export class UsageComponent {
    public State = ref<boolean>(false);

    private static instance: UsageComponent = new UsageComponent();
    /**
     * 应用组件
     */
    public static get Default(): UsageComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch(this.Module, this.OnModuleChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.CameraFrameId, this.UpdateFrameIdAsync.bind(this)));
        this.watchStopHandles.push(watch(this.LaneLineState, this.OnLaneLineStateChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.ObstructionState, this.OnObstructionStateChangedAsync.bind(this)));

        this.watchStopHandles.push(watch(this.Speed, this.OnVehicleInformationChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.TurnLightState, this.OnVehicleInformationChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.WiperState, this.OnVehicleInformationChangedAsync.bind(this)));

        this.watchStopHandles.push(watch(this.VideoPlaying, this.OnVideoPlayingChangedAsync.bind(this)));
        this.watchStopHandles.push(watch(this.VideoMode, this.OnVideoModeChangedAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public Options: Ref<Array<string>> = ref(['相机功能', '车道线识别']);


    public Module: Ref<string> = ref('');

    public CameraInformationVisibility: Ref<boolean> = ref(false);

    public CameraFrameIdOptions = new Map<number, string>([
        [4, '左相机图像'],
        [8, '右相机图像'],
        [64, '视差图像'],
    ]);

    public CameraFrameId = ref(0);

    public CameraFrameName = computed(() => this.CameraFrameIdOptions.get(this.CameraFrameId.value) ?? '');

    /**
     * 相机功能 - 行驶线状态
     */
    public LaneLineState: Ref<boolean> = ref(false);
    /**
     * 相机功能 - 障碍物状态
     */
    public ObstructionState: Ref<boolean> = ref(false);

    public Speed = ref(0);
    public AcceleratorPedalPercent = ref(0);
    public BrakePedalPercent = ref(0);
    public TurnLightState = ref(0);
    public WiperState = ref(0);
    public OnlyShowObstructionDistanceState = ref(false);
    public ShowObstructionInformationState = ref(false);
    public OnlyShowNearestObstructionState = ref(false);
    public ShowDrivingAreaLineState = ref(false);

    public Video: Ref<string> = ref('../UI/static/BinocularCamera/默认视频.mp4');

    public VideoMillisecondPosition: Ref<number> = ref(0);
    public VideoTotalMillisecond: Ref<number> = ref(1000 * 100);
    public VideoSpeed: Ref<number> = ref(1);
    public VideoPlaying: Ref<boolean> = ref(false);
    public VideoLastUpdateTime: Ref<number> = ref(0);

    public VideoMode: Ref<number> = ref(0);

    private watchStopHandles: Array<WatchStopHandle> = [];

    private hasInitialized: boolean = false;

    private lastUpdateVehicleInformationTime: number = 0;

    private volume: number = 0;
    private effect: number = 0;


    public async LoadDeviceAsync() {
        // throw new Error('Method not implemented.');
          this.State.value = false;
          // await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionRequest());
          this.VideoPlaying.value = false;
          this.VideoMillisecondPosition.value = 0;
          await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionOpenRequest('0'));
        }


    public async Awake(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        WebWindowComponent.Default.SetTransparentBackground();
        TooltipComponent.Default.Clear();

        this.volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
        this.effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(this.volume);

        if (!this.hasInitialized) {
            await this.LoadAsync();

            this.hasInitialized = true;
        }

        // this.Options.value.splice(0, this.Options.value.length);
        // if (BinocularCameraComponent.Default.Status.value != '设备连接成功') {
        //     this.Options.value.push('车道线识别');
        // } else {
        //     this.Options.value.push('相机功能');
        //     this.Options.value.push('车道线识别');
        // }

        // this.Module.value = this.Options.value[this.Options.value.length - 1];
        
        
        const response = await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageOpenRequest());
        ModalComponent.Default.isConnect.value = response.Message
        

        this.Options.value.splice(0, this.Options.value.length);
        if (response.Error == 0) {
            this.Options.value.push('相机功能');
            this.Options.value.push('车道线识别');

            this.Module.value = '相机功能';
            await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionShowRequest());
        } else {
            this.Options.value.push('车道线识别');

            if (this.Module.value != '车道线识别') {
                this.Module.value = '车道线识别';
            } else {
                await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionShowRequest());
            }

            this.Module.value = '车道线识别';
        }
        // if (this.Module.value == '车道线识别') {
        //     await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionShowRequest());
        // } else {
        //     const response = await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageOpenRequest());
        //     if (response.Error != 0) {
        //         this.Options.value.splice(0, this.Options.value.length);
        //         this.Options.value.push('车道线识别');
        //         this.Module.value = '车道线识别';
        //     }
        // }

        await PostProcessLayerComponent.Default.RemoveEffectAsync(this.volume, this.effect);
        await PostProcessLayerComponent.Default.RemoveVolumeAsync(this.volume);

        lock.Dispose();
    }

    public async Destroy(): Promise<void> {
        const lock = await BinocularCameraComponent.Default.WaitAsync();

        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageHideRequest());

        this.VideoPlaying.value = false;
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionHideRequest());

        lock.Dispose();
    }

    private async LoadAsync(): Promise<void> {
        this.CameraFrameId.value = 4;

        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageRequest());
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionRequest());

        const response = await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageOpenRequest());
        if (response.Error != 0) {
            if (import.meta.env.DEV) {
                return;
            }

            const options = ModalOptions.Default()
                .WithPrefix('/src/components/Apps/BinocularCamera/')
                .WithType('Exit')
                .WithTitle('信息')
                .WithContent(response.Message)
                .WithButtons(['确定']);
            await ModalComponent.Default.PopupAsync(options);

            this.Options.value.splice(0, this.Options.value.length);
            this.Options.value.push('车道线识别');
            this.Module.value = '车道线识别';
        }
    }

    public async OpenVideoAsync(): Promise<void> {
        if (import.meta.env.DEV) {
            return;
        }

        if (UsageComponent.Default.Video.value.length == 0) {
            return;
        }
        
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionOpenRequest(UsageComponent.Default.Video.value));
        
        this.VideoMode.value = 0;
        this.VideoMillisecondPosition.value = 0;
        this.VideoPlaying.value = false;
    }

    private async OnVideoModeChangedAsync(): Promise<void> {
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionModeRequest(this.VideoMode.value));
    }

    public async UpdateFrameIdAsync(frameId: number): Promise<void> {
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraFrameRequest(frameId));
    }

    private async OnModuleChangedAsync(module: string): Promise<void> {
        console.log('ModalComponent.Default.isConnect.value',ModalComponent.Default.isConnect.value);
        
        if (module == '车道线识别') {
            await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageHideRequest());
            if(ModalComponent.Default.isConnect.value == '请检查设备连接状况！'){
                const response: ClientMessage.BinocularCameraLaneDetectionOpenResponse = await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionOpenRequest(UsageComponent.Default.Video.value));                
                this.VideoPlaying.value = false;
                this.VideoMillisecondPosition.value = 0;
                this.VideoTotalMillisecond.value = response.Duration;
                await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionShowRequest());
    
                if (response.Error != 0) {
                    if (import.meta.env.DEV) {
                        return;
                    }
                    const options = ModalOptions.Default()
                        .WithPrefix('/src/components/Apps/BinocularCamera/')
                        .WithType('Exit')
                        .WithTitle('信息')
                        .WithContent(response.Message)
                        .WithButtons(['确定']);
                    await ModalComponent.Default.PopupAsync(options);
                }
            }
        } else {
            this.VideoPlaying.value = false;
            await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraLaneDetectionHideRequest());

            const response = await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraDeviceImageOpenRequest());
            if (response.Error != 0) {
                if (import.meta.env.DEV) {
                    return;
                }

                this.Options.value.splice(0, this.Options.value.length);
                this.Options.value.push('车道线识别');
                this.Module.value = '车道线识别';

                // const options = ModalOptions.Default()
                //     .WithPrefix('/src/components/Apps/BinocularCamera/')
                //     .WithType('Exit')
                //     .WithTitle('信息')
                //     .WithContent(response.Message)
                //     .WithButtons(['确定']);
                // await ModalComponent.Default.PopupAsync(options);
            }
        }
    }

    private async OnLaneLineStateChangedAsync(state: boolean): Promise<void> {
        if (!state) {
            await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraFrameRequest(this.CameraFrameId.value));
            return;
        }
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraFrameRequest(16384));
    }

    private async OnObstructionStateChangedAsync(state: boolean): Promise<void> {
        if (!state) {
            await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraFrameRequest(this.CameraFrameId.value));
            return;
        }
        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraFrameRequest(2048));
    }

    private async OnVehicleInformationChangedAsync(): Promise<void> {
        const interval = 1000;
        this.lastUpdateVehicleInformationTime = Date.now();
        const timer = this.lastUpdateVehicleInformationTime + interval;
        await TimerComponent.Default.WaitAsync(interval);
        if (timer - this.lastUpdateVehicleInformationTime != interval) {
            return;
        }

        const request = new ClientMessage.BinocularCameraVehicleInformationUpdateRequest(
            0,
            this.TurnLightState.value == -1,
            this.TurnLightState.value == 1,
            this.WiperState.value != 0,
            this.BrakePedalPercent.value != 0,
            this.Speed.value | 0
        );
        await WebSocketComponent.Default.PostMessageAsync(request);
    }

    public async OnNavigateToChildAsync(value: string): Promise<void> {
        this.volume = await PostProcessLayerComponent.Default.AddVolumeAsync();
        this.effect = await PostProcessLayerComponent.Default.AddKawaseBlurAsync(this.volume);

        await RouterComponent.Default.NavigateToChildAsync(value);
    }

    public async NavigateToPreviousAsync(): Promise<void> {
        RouterComponent.Default.NavigateToPrevious();

        await PostProcessLayerComponent.Default.RemoveEffectAsync(this.volume, this.effect);
        await PostProcessLayerComponent.Default.RemoveVolumeAsync(this.volume);
    }

    //#region 视频播放

    private async OnVideoPlayingChangedAsync(state: boolean): Promise<void> {
        console.log(state,'1111111111111111111111111111');
        
        if (state && this.VideoMillisecondPosition.value == this.VideoTotalMillisecond.value) {
            this.VideoMillisecondPosition.value = 0;
        }

        await WebSocketComponent.Default.PostMessageAsync(new ClientMessage.BinocularCameraVideoSettingsRequest(
            this.VideoPlaying.value,
            this.VideoMillisecondPosition.value * 100 / this.VideoTotalMillisecond.value | 0,
            this.VideoSpeed.value * 100,
        ));

        if (!state) {
            
            return;
        }

        this.VideoLastUpdateTime.value = Date.now();
        this.UpdateVideo();
    }

    private UpdateVideo(): void {
        
        if (!this.VideoPlaying.value || this.VideoMillisecondPosition.value == this.VideoTotalMillisecond.value) {
            this.VideoPlaying.value = false;
            return;
        }

        const timer = Date.now();
        const duration = timer - this.VideoLastUpdateTime.value;
        this.VideoLastUpdateTime.value = timer;
        if (duration != 0) {
            this.VideoMillisecondPosition.value = Math.min(this.VideoMillisecondPosition.value + duration * this.VideoSpeed.value, this.VideoTotalMillisecond.value);
        }
        window.requestAnimationFrame(this.UpdateVideo.bind(this));
    }

    public OnPrepareSeek(): void {
        this.VideoPlaying.value = false;
        // window.addEventListener('mouseup', this.OnSeek.bind(this));
    }

    public OnSeek(): void {
        const percent = this.VideoMillisecondPosition.value * 100 / this.VideoTotalMillisecond.value | 0;
        if (percent == 100) {
            this.VideoPlaying.value = false;
        } else {
            this.VideoPlaying.value = true;
        } 
        // window.removeEventListener('mouseup', this.OnSeek.bind(this));
    }

    //#endregion
}

class Point {
    public Name: string;
    public X: number;
    public Y: number;

    constructor(name: string, x: number = 0, y: number = 0) {
        this.Name = name;
        this.X = x;
        this.Y = y;
    }
}

/**
 * 车道线识别设置
 */
export class LaneSettingsComponent {
    private static instance: LaneSettingsComponent = new LaneSettingsComponent();
    /**
     * 车道线识别设置
     */
    public static get Default(): LaneSettingsComponent {
        return this.instance;
    }

    constructor() {
        window.addEventListener('unload', this.Dispose.bind(this));

        this.watchStopHandles.push(watch([this.BlurLevel, this.Points, this.CannyLow, this.CannyHigh, this.ShowLaneState, this.ShowAreaState, this.LaneColor, this.LaneAlpha, this.AreaColor, this.AreaAlpha], this.UpdateSettingsAsync.bind(this)));
    }

    Dispose() {
        window.removeEventListener('unload', this.Dispose);

        for (const watchStopHandle of this.watchStopHandles) {
            watchStopHandle();
        }
        this.watchStopHandles.clear();
    }

    public LastUpdateTime = ref(0);
    public BlurLevel = ref(3);

    public Points: UnwrapNestedRefs<Array<Point>> = reactive([
        new Point('A'),
        new Point('B'),
        new Point('C'),
        new Point('D'),
        new Point('E'),
        new Point('F'),
    ]);

    public CannyLow = ref(10);
    public CannyHigh = ref(30);

    public ShowLaneState = ref(false);
    public ShowAreaState = ref(false);

    public LaneColor = ref('#6BC167');
    public LaneAlpha = ref(100);
    public AreaColor = ref('#F9BE59');
    public AreaAlpha = ref(100);

    private watchStopHandles: Array<WatchStopHandle> = [];

    public async Awake(): Promise<void> {
    }

    public async Destroy(): Promise<void> {
    }

    public async UpdateSettingsAsync(): Promise<void> {
        this.LastUpdateTime.value = Date.now();
        const interval = 2000;
        const timer = this.LastUpdateTime.value + interval;
        await TimerComponent.Default.WaitAsync(interval);

        if (timer - this.LastUpdateTime.value == interval) {
            const request = new ClientMessage.BinocularCameraLaneDetectionSettingsRequest(
                this.BlurLevel.value | 0,
                this.Points.flatMap(point => [point.X, point.Y]),
                this.CannyLow.value,
                this.CannyHigh.value,
                this.ShowLaneState.value,
                [Number.parseInt(this.LaneColor.value.slice(5, 7), 16), Number.parseInt(this.LaneColor.value.slice(3, 5), 16), Number.parseInt(this.LaneColor.value.slice(1, 3), 16)],
                this.AreaAlpha.value | 0,
                this.ShowAreaState.value,
                [Number.parseInt(this.AreaColor.value.slice(5, 7), 16), Number.parseInt(this.AreaColor.value.slice(3, 5), 16), Number.parseInt(this.AreaColor.value.slice(1, 3), 16)],
                this.LaneAlpha.value | 0,
            );
            await WebSocketComponent.Default.PostMessageAsync(request);
        }
    }
}